<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[Balint Erdi's blog about Ember.js]]></title>
  <link href="http://balinterdi.com/atom.xml" rel="self"/>
  <link href="http://balinterdi.com/"/>
  <updated>2016-12-14T16:22:46+01:00</updated>
  <id>http://balinterdi.com/</id>
  <author>
    <name><![CDATA[I'm all about Ember.js recently]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[Two-way symmetric relationships in Ember with JSON API - Part 2]]></title>
    <link href="http://balinterdi.com/2016/11/29/two-way-symmetric-relationships-in-ember-with-jsonapi-part-2.html"/>
    <updated>2016-11-29T13:55:00+01:00</updated>
    <id>http://balinterdi.com/2016/11/29/two-way-symmetric-relationships-in-ember-with-jsonapi-part-2</id>
    <content type="html"><![CDATA[<p>In <a href="http://balinterdi.com/2016/11/17/two-way-symmetric-relationships-in-ember-with-jsonapi-part-1.html">Part 1</a> of this series, we saw what symmetric relationships are, how to
model them on the back-end (using Rails) and how to implement a simple app that
displays such relationships in Ember.js, adhering to the JSON API specification
for serializing data.</p>

<p>The solution we came up with worked but was a very naive one. For N relationships
a resource had, it made 2N+1 queries to the back-end to display them. We should
do better and in this post we&#8217;ll see how.</p>

<p>(If you haven&#8217;t read <a href="http://balinterdi.com/2016/11/17/two-way-symmetric-relationships-in-ember-with-jsonapi-part-1.html">the previous post</a>, this one will not make much sense,
so I recommend to at least skim it before you delve into this one.)</p>

<h2>One request to rule them all</h2>

<p>We&#8217;d observed that for each person whose friendships we wanted to observe, our
application made 2N+1 requests. One to grab the friendships themselves, and then
two requests for each friendship in that collection, one to fetch the
friender, one to fetch the friended person.</p>

<p><img src="http://balinterdi.com/images/posts/symmetric-relationships/too-many-xhrs.png" alt="Too many XHRs" /></p>

<p>We also noticed that those people (instances of the Person model) had already
been fetched at that point so the extra requests were for nothing. Our mission
is thus to reduce the 2N+1 requests to a single one, the one that fetches the
friendships.</p>

<h2>How would Ember (Data) know?</h2>

<p>If we take a look at the data returned by the request for friendships, you can
see that both the <code>friended</code> and <code>friender</code> end of each are just links with no
type or identity information (like <code>/friendships/1/friended</code>). This is all
that&#8217;s needed for an asynchronous relationship, since the client (Ember Data, in
this case) can just fetch the relationship data when/if it needs it.</p>

<p><img src="http://balinterdi.com/images/posts/symmetric-relationships/relationship-without-resource-linkage-data.png" alt="No linkage data" /></p>

<p>The solution, then, might be to include some data about the resource that the
relationship refers to. In the JSON API vocabulary this is called <a href="http://jsonapi.org/format/#document-resource-object-linkage">resource
linkage</a>:</p>

<blockquote>
Resource linkage in a compound document allows a client to link together all
of the included resource objects without having to GET any URLs via links.
</blockquote>


<p>Digging around in the <a href="https://github.com/cerebris/jsonapi-resources">jsonapi-resources source</a>, we find a relationship
option called <code>always_include_linkage_data</code> that seems to do what we need. Let&#8217;s
add that to the relationships of the friendship resource and see:</p>

<figure class='code'><figcaption><span></span></figcaption><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>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="c1"># app/resources/friendship_resource.rb</span>
</span><span class='line'><span class="k">class</span> <span class="nc">FriendshipResource</span> <span class="o">&lt;</span> <span class="ss">JSONAPI</span><span class="p">:</span><span class="ss">:Resource</span>
</span><span class='line'>  <span class="n">has_one</span> <span class="ss">:friender</span><span class="p">,</span> <span class="n">always_include_linkage_data</span><span class="p">:</span> <span class="kp">true</span>
</span><span class='line'>  <span class="n">has_one</span> <span class="ss">:friended</span><span class="p">,</span> <span class="n">always_include_linkage_data</span><span class="p">:</span> <span class="kp">true</span>
</span><span class='line'>  <span class="n">attributes</span> <span class="ss">:strength</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>If we now reload our Ember app, we see how a <code>data</code> key was added to each
relationship in the response, uniquely identifying the person resource that is
the friender (or friended) in the friendship relationship:</p>

<p><img src="http://balinterdi.com/images/posts/symmetric-relationships/relationship-with-resource-linkage-data.png" alt="Relationship with linkage data" /></p>

<p>Furthermore, the extra XHRs we wanted to eliminate are now indeed gone as Ember
Data is smart enough to just use the referred resources that are already in the
store:</p>

<p><img src="http://balinterdi.com/images/posts/symmetric-relationships/no-useless-xhrs.png" alt="Just the XHRs we need" /></p>

<h2>Let&#8217;s just be friends (not friendeds or frienders)</h2>

<p>We have now achieved what we&#8217;d wanted and only have to make one request per
person to fetch and display their friendships.</p>

<p>It looks a bit weird, though, that when a person&#8217;s friendships are displayed, we
also display the person&#8217;s name, too:</p>

<p><img src="http://balinterdi.com/images/posts/symmetric-relationships/friendships-step-1.png" alt="Mike McCready's friendships - Part 1" /></p>

<p>Let&#8217;s fix that by transforming the <code>friendships</code> of the person to an array where
each item only contains the friend&#8217;s name (and the strength of the friendship):</p>

<figure class='code'><figcaption><span></span></figcaption><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>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<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='js'><span class='line'><span class="c1">// app/controllers/people/show.js</span>
</span><span class='line'><span class="kr">import</span> <span class="nx">Ember</span> <span class="nx">from</span> <span class="s1">&#39;ember&#39;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="kr">const</span> <span class="p">{</span> <span class="nx">Controller</span><span class="p">,</span> <span class="nx">computed</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">Ember</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="kr">export</span> <span class="k">default</span> <span class="nx">Controller</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span>
</span><span class='line'>  <span class="nx">friendships</span><span class="o">:</span> <span class="nx">computed</span><span class="p">(</span><span class="s1">&#39;model.friendships.[]&#39;</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="kd">let</span> <span class="nx">person</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;model&#39;</span><span class="p">);</span>
</span><span class='line'>    <span class="kd">let</span> <span class="nx">friendships</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;model.friendships&#39;</span><span class="p">);</span>
</span><span class='line'>    <span class="k">return</span> <span class="nx">friendships</span><span class="p">.</span><span class="nx">map</span><span class="p">((</span><span class="nx">friendship</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>      <span class="kd">let</span> <span class="nx">friend</span><span class="p">;</span>
</span><span class='line'>      <span class="k">if</span> <span class="p">(</span><span class="nx">friendship</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;friended.id&#39;</span><span class="p">)</span> <span class="o">===</span> <span class="nx">person</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;id&#39;</span><span class="p">))</span> <span class="p">{</span>
</span><span class='line'>        <span class="nx">friend</span> <span class="o">=</span> <span class="nx">friendship</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;friender&#39;</span><span class="p">);</span>
</span><span class='line'>      <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span><span class='line'>        <span class="nx">friend</span> <span class="o">=</span> <span class="nx">friendship</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;friended&#39;</span><span class="p">);</span>
</span><span class='line'>      <span class="p">}</span>
</span><span class='line'>      <span class="k">return</span> <span class="p">{</span>
</span><span class='line'>        <span class="nx">friend</span><span class="p">,</span>
</span><span class='line'>        <span class="nx">strength</span><span class="o">:</span> <span class="nx">friendship</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;strength&#39;</span><span class="p">)</span>
</span><span class='line'>      <span class="p">};</span>
</span><span class='line'>    <span class="p">});</span>
</span><span class='line'>  <span class="p">})</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<p>Nothing fancy going on, we check which end of the relationship the person in
question (the <code>model</code>) is, and then only return the other end.</p>

<p>We should now use <code>friendships</code> in the template instead of <code>model.friendships</code>:</p>

<div>
  <pre><code class='html'>&lt;div class=&quot;panel panel-default&quot;&gt;
  &lt;div class=&quot;panel-heading&quot;&gt;
    &lt;h3 class=&quot;panel-title&quot;&gt;Friends of {{model.name}}&lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class=&quot;panel-body&quot;&gt;
    {{#if friendships.length}}
      &lt;ul class=&quot;friend-list&quot;&gt;
        {{#each friendships as |friendship|}}
          &lt;li class=&quot;friend-list-item&quot;&gt;
            &lt;span class=&quot;name&quot;&gt;{{friendship.friend.name}}&lt;/span&gt;
            &lt;span class=&quot;badge&quot;&gt;{{friendship.strength}}&lt;/span&gt;
          &lt;/li&gt;
        {{/each}}
      &lt;/ul&gt;
    {{else}}
      &lt;div class=&quot;empty-list&quot;&gt;
        &lt;p class=&quot;empty-message&quot;&gt;{{model.name}} has no friends :(&lt;/p&gt;
      &lt;/div&gt;
    {{/if}}
  &lt;/div&gt;
&lt;/div&gt;</code></pre>
</div>


<p>It works, we indeed only see the friend&#8217;s name, not the person&#8217;s:</p>

<p><img src="http://balinterdi.com/images/posts/symmetric-relationships/only-friend-name.png" alt="Relationship with linkage data" /></p>

<h2>Resources</h2>

<p>Hopefully you can now implement a symmetric relationship with relative
ease, the next time you encounter it.</p>

<p>I made the source code of both <a href="https://github.com/balinterdi/ember-two-way-symmetric-relationships">the Ember app</a> and the <a href="https://github.com/balinterdi/two-way-symmetric-relationships-api">Rails API</a>
available on Github. If you want to learn more about the jsonapi-resources gem,
I suggest you visit <a href="http://jsonapi-resources.com/">the documentation site</a>.</p>

<p>Finally, if you&#8217;d like to receive the series as a pdf, fill out the form below
and I&#8217;ll send it to you right away!</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Two-way symmetric relationships in Ember with JSON API - Part 1]]></title>
    <link href="http://balinterdi.com/2016/11/17/two-way-symmetric-relationships-in-ember-with-jsonapi-part-1.html"/>
    <updated>2016-11-17T12:52:00+01:00</updated>
    <id>http://balinterdi.com/2016/11/17/two-way-symmetric-relationships-in-ember-with-jsonapi-part-1</id>
    <content type="html"><![CDATA[<h2>Definition</h2>

<p>In data modelling, a symmetric relationship is a special kind of relationship
where the description of the relationship from the perspective of one end of
the relationship is identical to looking at it from the perspective of the other
end.</p>

<p>Friendship between people is a good example. If Megan is Selma&#8217;s friend, it
follows that Selma is Megan&#8217;s friend, too. On the other hand, the &#8220;knows&#8221;
relationship between two people is not a symmetric one. I might know Danny
Carey (the drummer of Tool), but that does not imply he knows me.</p>

<h2>Historical background</h2>

<p>My research into how to model and implement such a relationship in an Ember
application was sparked by <a href="http://stackoverflow.com/questions/34186435/modelling-two-way-symmetric-relationships-in-ember">this Stack Overflow question</a> that was posed by
a reader of <a href="http://rockandrollwithemberjs.com">my book</a>. It was more difficult than I thought it would be so I
was intrigued to find the (an) answer.</p>

<p>My solution turned out to have a fairly large API component, too, so the
following post will show both the server-side implementation (in Rails) and the
client-side one (in Ember).</p>

<p>If you don&#8217;t speak Rails, fear not. The code is straightforward and easy to
understand without any substantial Rails knowledge, thanks in most part to the gem that
makes it extremely easy to serialize data models and relationships to json:api
format, <a href="https://github.com/cerebris/jsonapi-resources">jsonapi-resources</a>.</p>

<h2>Data modelling</h2>

<p>We&#8217;ll start with the data modelling part, which is the Rails side.</p>

<p>To be able to model our problem in the data layer, let&#8217;s say that Friendships
have a <code>friender</code> and a <code>friended</code> end of the relationship and a strength
attribute that measures how strong their friendship is.</p>

<p>We should create a (data) migration that will create a database table when run:</p>

<pre><code>    $ rails g migration create_friendships
</code></pre>

<p>Let&#8217;s fill in the generated migration with the above attributes:</p>

<figure class='code'><figcaption><span></span></figcaption><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>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">class</span> <span class="nc">CreateFriendships</span> <span class="o">&lt;</span> <span class="ss">ActiveRecord</span><span class="p">:</span><span class="ss">:Migration</span>
</span><span class='line'>  <span class="k">def</span> <span class="nf">change</span>
</span><span class='line'>    <span class="n">create_table</span> <span class="ss">:friendships</span> <span class="k">do</span> <span class="o">|</span><span class="n">t</span><span class="o">|</span>
</span><span class='line'>      <span class="n">t</span><span class="o">.</span><span class="n">integer</span> <span class="ss">:friender_id</span>
</span><span class='line'>      <span class="n">t</span><span class="o">.</span><span class="n">integer</span> <span class="ss">:friended_id</span>
</span><span class='line'>      <span class="n">t</span><span class="o">.</span><span class="n">integer</span> <span class="ss">:strength</span>
</span><span class='line'>      <span class="n">t</span><span class="o">.</span><span class="n">timestamps</span> <span class="ss">null</span><span class="p">:</span> <span class="kp">false</span>
</span><span class='line'>    <span class="k">end</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>A Friendship, then, is between two people (Persons), so let&#8217;s define that in the
corresponding model file:</p>

<figure class='code'><figcaption><span></span></figcaption><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='ruby'><span class='line'><span class="c1"># app/models/friendship.rb</span>
</span><span class='line'><span class="k">class</span> <span class="nc">Friendship</span> <span class="o">&lt;</span> <span class="ss">ActiveRecord</span><span class="p">:</span><span class="ss">:Base</span>
</span><span class='line'>  <span class="n">belongs_to</span> <span class="ss">:friender</span><span class="p">,</span> <span class="n">class_name</span><span class="p">:</span> <span class="no">Person</span>
</span><span class='line'>  <span class="n">belongs_to</span> <span class="ss">:friended</span><span class="p">,</span> <span class="n">class_name</span><span class="p">:</span> <span class="no">Person</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>We&#8217;ll want to list all the friendships a person has so a <code>friendships</code> method
needs to be added to the Person class:</p>

<figure class='code'><figcaption><span></span></figcaption><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>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="c1"># app/models/person.rb</span>
</span><span class='line'><span class="k">class</span> <span class="nc">Person</span> <span class="o">&lt;</span> <span class="ss">ActiveRecord</span><span class="p">:</span><span class="ss">:Base</span>
</span><span class='line'>  <span class="k">def</span> <span class="nf">friendships</span>
</span><span class='line'>    <span class="no">Friendship</span><span class="o">.</span><span class="n">where</span><span class="p">(</span><span class="s2">&quot;friender_id = ? OR friended_id = ?&quot;</span><span class="p">,</span> <span class="nb">id</span><span class="p">,</span> <span class="nb">id</span><span class="p">);</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>We select the friendships where either the <code>friender</code> or the <code>friended</code> is the
person we query it for. This is where the symmetric aspect of the relationship
is implemented. We don&#8217;t care if the person friended somebody or if that
somebody friended him, they are friends.</p>

<p>Note that modelling it this way, we could split up the symmetric relationship
into the two constituent parts. We could return only the friendships where the
person in question &#8220;initiated&#8221; it (was the friender), or &#8220;let himself be
friended&#8221; (was the friender).</p>

<h2>Server endpoints, resources, serializing relationships</h2>

<p>We could now turn our attention to setting up the endpoints and serializing the
model, and relationship data for the client application to consume. First, let&#8217;s
install <a href="https://github.com/cerebris/jsonapi-resources">the jsonapi-resources gem</a>:</p>

<pre><code>    $ gem install jsonapi-resources
</code></pre>

<p>This gives us a jsonapi:resource generator that we can use to create both the
endpoints and the serializer for our resources.</p>

<pre><code>    $ rails generate jsonapi:resource person
    $ rails generate jsonapi:resource friendship
</code></pre>

<p>The created resources are placed in the <code>app/resources</code> folder. Let&#8217;s add the
attributes we want to serialize for each one:</p>

<figure class='code'><figcaption><span></span></figcaption><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='ruby'><span class='line'><span class="c1"># app/resources/person_resource.rb</span>
</span><span class='line'><span class="k">class</span> <span class="nc">PersonResource</span> <span class="o">&lt;</span> <span class="ss">JSONAPI</span><span class="p">:</span><span class="ss">:Resource</span>
</span><span class='line'>  <span class="n">attributes</span> <span class="ss">:name</span>
</span><span class='line'>  <span class="n">has_many</span> <span class="ss">:friendships</span><span class="p">,</span> <span class="n">class_name</span><span class="p">:</span> <span class="s2">&quot;Friendship&quot;</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>




<figure class='code'><figcaption><span></span></figcaption><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>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="c1"># app/resources/friendship_resource.rb</span>
</span><span class='line'><span class="k">class</span> <span class="nc">FriendshipResource</span> <span class="o">&lt;</span> <span class="ss">JSONAPI</span><span class="p">:</span><span class="ss">:Resource</span>
</span><span class='line'>  <span class="n">has_one</span> <span class="ss">:friender</span>
</span><span class='line'>  <span class="n">has_one</span> <span class="ss">:friended</span>
</span><span class='line'>  <span class="n">attributes</span> <span class="ss">:strength</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>Creating the endpoints is no more work than adding a <code>jsonapi_resources</code> call
for each resource in the router configuration:</p>

<figure class='code'><figcaption><span></span></figcaption><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='ruby'><span class='line'><span class="c1"># config/routes.rb</span>
</span><span class='line'><span class="no">Rails</span><span class="o">.</span><span class="n">application</span><span class="o">.</span><span class="n">routes</span><span class="o">.</span><span class="n">draw</span> <span class="k">do</span>
</span><span class='line'>  <span class="n">jsonapi_resources</span> <span class="ss">:people</span>
</span><span class='line'>  <span class="n">jsonapi_resources</span> <span class="ss">:friendships</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>The gem also provides a controller generator so let&#8217;s use it to create controllers for our resources:</p>

<pre><code>    $ rails generate jsonapi:controller person
    $ rails generate jsonapi:controller friendship
</code></pre>

<p>They can be left empty but they need to be created in a way that they are
descendants of JSONAPI::ResourceController (the generator takes care of that):</p>

<figure class='code'><figcaption><span></span></figcaption><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>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="c1"># app/controllers/people_controller.rb</span>
</span><span class='line'><span class="k">class</span> <span class="nc">PeopleController</span> <span class="o">&lt;</span> <span class="ss">JSONAPI</span><span class="p">:</span><span class="ss">:ResourceController</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>




<figure class='code'><figcaption><span></span></figcaption><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>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="c1"># app/controllers/friendships_controller.rb</span>
</span><span class='line'><span class="k">class</span> <span class="nc">FriendshipsController</span> <span class="o">&lt;</span> <span class="ss">JSONAPI</span><span class="p">:</span><span class="ss">:ResourceController</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>The back-end is now done, we can switch our focus to the Ember app.</p>

<h2>The front-end</h2>

<p>We want a list of people (<a href="http://rockandrollwithemberjs.com">rock stars</a>, of course) and then have a list of
their friendships on the person details page.</p>

<p><img src="http://balinterdi.com/images/posts/symmetric-relationships/friendships-step-1.png" alt="Mike McCready's frienships - Part 1" /></p>

<p>The first step is to set up the routes:</p>

<figure class='code'><figcaption><span></span></figcaption><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>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="p">(...)</span>
</span><span class='line'><span class="nx">Router</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>  <span class="k">this</span><span class="p">.</span><span class="nx">route</span><span class="p">(</span><span class="s1">&#39;people&#39;</span><span class="p">,</span> <span class="p">{</span> <span class="nx">path</span><span class="o">:</span> <span class="s1">&#39;/&#39;</span> <span class="p">},</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">this</span><span class="p">.</span><span class="nx">route</span><span class="p">(</span><span class="s1">&#39;show&#39;</span><span class="p">,</span> <span class="p">{</span> <span class="nx">path</span><span class="o">:</span> <span class="s1">&#39;/people/:person_id&#39;</span> <span class="p">});</span>
</span><span class='line'>  <span class="p">});</span>
</span><span class='line'><span class="p">});</span>
</span><span class='line'>
</span><span class='line'><span class="kr">export</span> <span class="k">default</span> <span class="nx">Router</span><span class="p">;</span>
</span></code></pre></td></tr></table></div></figure>


<p>The model hooks for these routes are the classic, &#8220;fetch&#8217;em all&#8221; and &#8220;fetch the
one that matches the id&#8221; methods of Ember Data&#8217;s store:</p>

<figure class='code'><figcaption><span></span></figcaption><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>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="c1">// app/routes/people.js</span>
</span><span class='line'><span class="kr">import</span> <span class="nx">Ember</span> <span class="nx">from</span> <span class="s1">&#39;ember&#39;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="kr">export</span> <span class="k">default</span> <span class="nx">Ember</span><span class="p">.</span><span class="nx">Route</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span>
</span><span class='line'>  <span class="nx">model</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">store</span><span class="p">.</span><span class="nx">findAll</span><span class="p">(</span><span class="s1">&#39;person&#39;</span><span class="p">);</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>




<figure class='code'><figcaption><span></span></figcaption><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>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="c1">// app/routes/people/show.js</span>
</span><span class='line'><span class="kr">import</span> <span class="nx">Ember</span> <span class="nx">from</span> <span class="s1">&#39;ember&#39;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="kr">export</span> <span class="k">default</span> <span class="nx">Ember</span><span class="p">.</span><span class="nx">Route</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span>
</span><span class='line'>  <span class="nx">model</span><span class="p">(</span><span class="nx">params</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">store</span><span class="p">.</span><span class="nx">findRecord</span><span class="p">(</span><span class="s1">&#39;person&#39;</span><span class="p">,</span> <span class="nx">params</span><span class="p">.</span><span class="nx">person_id</span><span class="p">);</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<p>Before we move on to writing the templates, let&#8217;s define the models:</p>

<figure class='code'><figcaption><span></span></figcaption><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>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<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='js'><span class='line'><span class="c1">// app/models/person.js</span>
</span><span class='line'><span class="kr">import</span> <span class="nx">DS</span> <span class="nx">from</span> <span class="s1">&#39;ember-data&#39;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="kr">const</span> <span class="p">{</span> <span class="nx">Model</span><span class="p">,</span> <span class="nx">attr</span><span class="p">,</span> <span class="nx">hasMany</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">DS</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="kr">export</span> <span class="k">default</span> <span class="nx">Model</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span>
</span><span class='line'>  <span class="nx">name</span><span class="o">:</span> <span class="nx">attr</span><span class="p">(),</span>
</span><span class='line'>  <span class="nx">friendships</span><span class="o">:</span> <span class="nx">hasMany</span><span class="p">(),</span>
</span><span class='line'>  <span class="nx">frienderFriendships</span><span class="o">:</span> <span class="nx">hasMany</span><span class="p">(</span><span class="s1">&#39;friendship&#39;</span><span class="p">,</span> <span class="p">{</span> <span class="nx">inverse</span><span class="o">:</span> <span class="s1">&#39;friender&#39;</span> <span class="p">}),</span>
</span><span class='line'>  <span class="nx">friendedFriendships</span><span class="o">:</span> <span class="nx">hasMany</span><span class="p">(</span><span class="s1">&#39;friendship&#39;</span><span class="p">,</span> <span class="p">{</span> <span class="nx">inverse</span><span class="o">:</span> <span class="s1">&#39;friended&#39;</span> <span class="p">}),</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>




<figure class='code'><figcaption><span></span></figcaption><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>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="c1">// app/models/friendship.js</span>
</span><span class='line'><span class="kr">import</span> <span class="nx">DS</span> <span class="nx">from</span> <span class="s1">&#39;ember-data&#39;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="kr">const</span> <span class="p">{</span> <span class="nx">Model</span><span class="p">,</span> <span class="nx">attr</span><span class="p">,</span> <span class="nx">belongsTo</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">DS</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="kr">export</span> <span class="k">default</span> <span class="nx">Model</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span>
</span><span class='line'>  <span class="nx">strength</span><span class="o">:</span> <span class="nx">attr</span><span class="p">(</span><span class="s1">&#39;number&#39;</span><span class="p">),</span>
</span><span class='line'>  <span class="nx">friender</span><span class="o">:</span> <span class="nx">belongsTo</span><span class="p">(</span><span class="s1">&#39;person&#39;</span><span class="p">,</span> <span class="p">{</span> <span class="nx">inverse</span><span class="o">:</span> <span class="s1">&#39;frienderFriendships&#39;</span> <span class="p">}),</span>
</span><span class='line'>  <span class="nx">friended</span><span class="o">:</span> <span class="nx">belongsTo</span><span class="p">(</span><span class="s1">&#39;person&#39;</span><span class="p">,</span> <span class="p">{</span> <span class="nx">inverse</span><span class="o">:</span> <span class="s1">&#39;friendedFriendships&#39;</span> <span class="p">}),</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<p>This is rather standard Ember Data stuff, possibly with the exception of the
<code>inverse</code> definitions. Since we have two relationships between <code>Person</code> and
<code>Friendship</code> we need to specify the other end of each relationship and that&#8217;s
what we do with the <code>inverse</code> option.</p>

<p>With the models and routes in place, we can now see what the templates should look like.</p>

<p>The top-level <code>people</code> route is again fairly straightforward:</p>

<div>
  <pre><code class='html'>// app/templates/people.hbs
&lt;div class=&quot;col-md-4&quot;&gt;
  &lt;div class=&quot;list-group&quot;&gt;
    {{#each model as |person|}}
      {{link-to person.name &#39;people.show&#39; person.id class=&quot;list-group-item&quot;}}
    {{/each}}
  &lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;col-md-8&quot;&gt;
  {{outlet}}
&lt;/div&gt;</code></pre>
</div>


<p>The <code>each</code> loop iterates through each person and renders a link for each of
those that will take us to the person details page, which will display the
person&#8217;s friendships.</p>

<p><img src="http://balinterdi.com/images/posts/symmetric-relationships/people-list-step-1.png" alt="List of people" /></p>

<h3>Listing a person&#8217;s friendships</h3>

<div>
  <pre><code class='html'>// app/templates/people/show.hbs
&lt;div class=&quot;panel panel-default&quot;&gt;
  &lt;div class=&quot;panel-heading&quot;&gt;
    &lt;h3 class=&quot;panel-title&quot;&gt;Friends of {{model.name}}&lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class=&quot;panel-body&quot;&gt;
    &lt;ul class=&quot;friend-list&quot;&gt;
      {{#each model.friendships as |friendship|}}
        &lt;li class=&quot;friend-list-item&quot;&gt;
          &lt;span class=&quot;name&quot;&gt;{{friendship.friender.name}}&lt;/span&gt;
          &lt;span class=&quot;name&quot;&gt;{{friendship.friended.name}}&lt;/span&gt;
          &lt;span class=&quot;badge&quot;&gt;{{friendship.strength}}&lt;/span&gt;
        &lt;/li&gt;
      {{/each}}
    &lt;/ul&gt;
  &lt;/div&gt;
&lt;/div&gt;</code></pre>
</div>


<p>There is nothing fancy going on here, either. The <code>model</code> is the person
retrieved in the route.  For each friendship that he has, the friender&#8217;s and
the friended&#8217;s name are rendered along with the strength of the relationship.
(Either <code>friender</code> or <code>friended</code> will be the person itself, but we can ignore that
in the first version.)</p>

<p>This naive approach works, the friendships for the selected person are listed correctly:</p>

<p><img src="http://balinterdi.com/images/posts/symmetric-relationships/friendships-step-1.png" alt="Mike McCready's friendships - Part 1" /></p>

<h2>A 2N+1 problem</h2>

<p>However, looking at the requests to the backend for just one page, one gets the
impression that we&#8217;re not done yet:</p>

<p><img src="http://balinterdi.com/images/posts/symmetric-relationships/too-many-xhrs.png" alt="Too many XHRs" /></p>

<p>For each friendship the person has, two requests are sent to the backend. One to
fetch the <code>friender</code> and another one to fetch the <code>friended</code> person. This is not
an <a href="https://www.sitepoint.com/silver-bullet-n1-problem/">N+1 query problem</a>, this is worse, a 2N+1 query problem!</p>

<p>On top of that, those requests are sent for no good reason as we&#8217;d previously
loaded the people referred by those <code>friended</code> and <code>friended</code> relationships.</p>

<p>In the next part, we&#8217;ll see how these wasteful requests can be eliminated and
we&#8217;ll also make the person details page less perplexing by not displaying the
person whose page we&#8217;re looking at in the relationships. Stay tuned!</p>

<p>UPDATE: <a href="http://balinterdi.com/2016/11/29/two-way-symmetric-relationships-in-ember-with-jsonapi-part-2.html">Part 2</a> is now available!</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Rock and Roll with Ember.js 2.9 is released]]></title>
    <link href="http://balinterdi.com/2016/11/16/rock-and-roll-with-ember-dot-js-2-dot-9-is-released.html"/>
    <updated>2016-11-16T14:17:00+01:00</updated>
    <id>http://balinterdi.com/2016/11/16/rock-and-roll-with-ember-dot-js-2-dot-9-is-released</id>
    <content type="html"><![CDATA[<p>I just published an updated version of the <a href="http://rockandrollwithemberjs.com">Rock and Roll with Ember.js book</a>. The app now runs on 2.9.1 and there are only
<a href="https://github.com/balinterdi/rarwe-issues/issues?q=is%3Aopen+is%3Aissue+milestone%3A2.9">a few really minor changes</a> this time.</p>

<p>If you&#8217;re looking to get started in Ember, I encourage you read a sample chapter below.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Enable FastBoot in your Ember app]]></title>
    <link href="http://balinterdi.com/2016/11/11/enable-fastboot-in-your-ember-app.html"/>
    <updated>2016-11-11T11:20:00+01:00</updated>
    <id>http://balinterdi.com/2016/11/11/enable-fastboot-in-your-ember-app</id>
    <content type="html"><![CDATA[<h2>What is FastBoot and why should you use it?</h2>

<p><a href="https://ember-fastboot.com/">FastBoot</a> is the awesome add-on that adds
server-side rendering to your Ember app. This will make users of your
application see the content of your page before any of the javascript is
downloaded. In other words, the <a href="https://blog.alexmaccaw.com/time-to-first-tweet">&#8220;time to first tweet&#8221;</a>
of your app is greatly reduced, which is a big win where and when people have slow
or unstable network connections.</p>

<p>Another advantage is that search engine crawlers will have an easier job
indexing your site, which brings SEO benefits.</p>

<p>Furthermore, your site will be readable with Javascript disabled which is
convenient for screen readers.</p>

<p>I recently went through the process of enabling the demo version of the
<a href="http://rockandrollwithemberjs.com">Rock and Roll application</a> to run in Fastboot.
Below, I&#8217;m going to tell you about the challenges I encountered and how I
overcame them in the hope that my journey will prove valuable when you do the same for
your app.</p>

<h2>Installing the add-on</h2>

<p>FastBoot is a regular Ember add-on, so installing it is piece of cake:</p>

<pre><code>$ ember install ember-cli-fastboot
</code></pre>

<p>I could then run</p>

<pre><code>$ ember fastboot
</code></pre>

<p>from the project&#8217;s directory and had the node server serving my application at
port 3000. It&#8217;s important to note that you should refresh your browser tab each
time you make changes to your code as FastBoot doesn&#8217;t (yet) auto-refresh the
way <code>ember server</code> does.</p>

<p>I then disabled JavaScript in my browser and then directed my browser to <code>http://localhost:3000</code>.</p>

<p>Disabling JavaScript in Chrome is most easily done by expanding the context menu
of Developer Tools and then clicking on Settings:</p>

<p><img src="http://balinterdi.com/images/posts/fastboot/disable-javascript-in-chrome.png" alt="Disable JavaScript" /></p>

<h2>Mirage is disabled in FastBoot mode</h2>

<p>My first obstacle turned out to be Mirage.</p>

<p>Mirage is a great tool for mocking server responses and even <a href="https://www.codeschool.com/blog/2016/07/07/building-an-ember-app-without-a-back-end/">prototyping your Ember app</a>.
I used it in development, too, and it turned out that since <a href="https://github.com/samselikoff/ember-cli-mirage/blob/24f994f4419f1b175c82331b00c3089e3f65c038/index.js#L106">it turns itself off</a>
when your app is running in FastBoot mode, the requests hitherto handled by
Mirage now went out and were thus unhandled.</p>

<p>The fix here was to disable Mirage in development (and, in my case, production,
too) and to make the requests against an actual API.</p>

<p>You also have to add the hosts that will serve your Ember app in FastBoot mode
to a list called hostWhitelist in your app&#8217;s configuration.</p>

<p>In my case, it contains the host I wanted to deploy it to and any localhost
port:</p>

<figure class='code'><figcaption><span></span></figcaption><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>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="c1">// config/environment.js</span>
</span><span class='line'><span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">environment</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="kd">var</span> <span class="nx">ENV</span> <span class="o">=</span> <span class="p">{</span>
</span><span class='line'>    <span class="p">(...)</span>
</span><span class='line'>    <span class="nx">fastboot</span><span class="o">:</span> <span class="p">{</span>
</span><span class='line'>      <span class="nx">hostWhitelist</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;demo.rockandrollwithemberjs.com&#39;</span><span class="p">,</span> <span class="sr">/^localhost:\d+$/</span><span class="p">]</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>  <span class="p">};</span>
</span></code></pre></td></tr></table></div></figure>


<h2>Serving assets</h2>

<p>When I restarted the <code>ember fastboot</code> and looked at the server-rendered version
of my app, I saw that the dynamic data was now correctly rendered on the page.
However, it did not have any styling.</p>

<p>A quick glance at <a href="https://ember-fastboot.com/docs/user-guide">the documentation</a> made me realize I needed to pass the
<code>serve-assets</code> option to the command so that it serves the css (and other asset)
files:</p>

<pre><code>$ ember fastboot --serve-assets
</code></pre>

<h2>document is not defined</h2>

<p>So now the main page, with the list of bands rendered fine but when I selected
one of the bands to have their songs displayed, I got the following error:</p>

<pre><code>Error while processing route: bands.band.songs document is not defined
</code></pre>

<p>Since Fastboot runs your Ember app in a node environment, not in the browser,
<code>document</code> is not present. In my case, I accessed <code>document</code> (through jQuery)
to set the document title, which does not work in FastBoot mode.</p>

<p>The user guide suggested to use <a href="https://github.com/kimroen/ember-cli-document-title">ember-cli-document-title</a>, a FastBoot
compatible way to set document titles. So my next step was to install that
add-on:</p>

<pre><code>$ ember install ember-cli-document-title
</code></pre>

<p>Armed with this great add-on, I only had to define a title (method) in the
corresponding route:</p>

<figure class='code'><figcaption><span></span></figcaption><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>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="c1">// app/routes/bands/band/songs.js</span>
</span><span class='line'><span class="kr">import</span> <span class="nx">Ember</span> <span class="nx">from</span> <span class="s1">&#39;ember&#39;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="kr">export</span> <span class="k">default</span> <span class="nx">Ember</span><span class="p">.</span><span class="nx">Route</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span>
</span><span class='line'>  <span class="p">(...)</span>
</span><span class='line'>  <span class="nx">title</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="kd">let</span> <span class="nx">bandName</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">modelFor</span><span class="p">(</span><span class="s1">&#39;bands.band&#39;</span><span class="p">).</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;name&#39;</span><span class="p">);</span>
</span><span class='line'>    <span class="k">return</span> <span class="err">`</span><span class="nx">$</span><span class="p">{</span><span class="nx">bandName</span><span class="p">}</span> <span class="nx">songs</span> <span class="o">-</span> <span class="nx">Rock</span> <span class="nx">and</span> <span class="nx">Roll</span><span class="err">`</span><span class="p">;</span>
</span><span class='line'>  <span class="p">},</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<h2>Missing dynamic content</h2>

<p>The next thing that did not work was that the songs for a specific band did not
load in FastBoot mode, the list of songs was empty each time.</p>

<p>Adolfo Builes and Jonathan Jackson helped me out by pointing out that songs are
loaded asynchronously. The request to fetch the songs was only fired when the
template rendered each song belonging to the band. FastBoot does not
know when the page is fully rendered and thus relies on the <code>beforeModel</code>,
<code>model</code> and <code>afterModel</code> route hooks having finished their work. When that
happened, the songs were not yet fetched and rendered on the screen yet:</p>

<p><img src="http://balinterdi.com/images/posts/fastboot/songs-missing.png" alt="Songs missing" /></p>

<p>The way to fix this was to block rendering in the <code>afterModel</code> hook, by
returning a promise that fetched the songs:</p>

<figure class='code'><figcaption><span></span></figcaption><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>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<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>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="c1">// app/routes/bands/band/songs.js</span>
</span><span class='line'><span class="kr">import</span> <span class="nx">Ember</span> <span class="nx">from</span> <span class="s1">&#39;ember&#39;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="kr">export</span> <span class="k">default</span> <span class="nx">Ember</span><span class="p">.</span><span class="nx">Route</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span>
</span><span class='line'>  <span class="nx">fastboot</span><span class="o">:</span> <span class="nx">Ember</span><span class="p">.</span><span class="nx">inject</span><span class="p">.</span><span class="nx">service</span><span class="p">(),</span>
</span><span class='line'>
</span><span class='line'>  <span class="nx">afterModel</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;fastboot.isFastBoot&#39;</span><span class="p">))</span> <span class="p">{</span>
</span><span class='line'>      <span class="kd">let</span> <span class="nx">band</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">modelFor</span><span class="p">(</span><span class="s1">&#39;bands.band&#39;</span><span class="p">);</span>
</span><span class='line'>      <span class="k">return</span> <span class="nx">band</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;songs&#39;</span><span class="p">);</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>  <span class="p">},</span>
</span><span class='line'>  <span class="p">(...)</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<p>As you can see, I only pre-fetch the songs in FastBoot mode. In the browser, I
let rendering start earlier, with a &#8220;pop-in&#8221; effect (which can be remedied in
several ways in the browser, too).</p>

<p>The songs now appeared in the FastBoot &#8220;view&#8221; of the app, too:</p>

<p><img src="http://balinterdi.com/images/posts/fastboot/songs-present.png" alt="Songs present" /></p>

<p>You can read more about this in the &#8220;Use Model Hooks to Defer Rendering&#8221; section
of <a href="https://ember-fastboot.com/docs/user-guide">the guide</a>.</p>

<h2>Fastboot-enabled hosting</h2>

<p>It&#8217;s fine to have FastBoot working in development but nobody actually needs
it to work in that environment. It has to work when deployed to a server.</p>

<p>The guide has <a href="https://ember-fastboot.com/docs/deploying">a whole page on deployment</a>, listing several deployment
options, from which I chose Heroku as it seemed the easiest option. And it really was.</p>

<p>All I had to do was to set the buildpack URL from my project:</p>

<pre><code>$ heroku buildpacks:set https://codon-buildpacks.s3.amazonaws.com/buildpacks/heroku/emberjs.tgz -a rarwe-demo
</code></pre>

<p>I then added a <code>static.json</code> file to the root of my project, to disable forcing
https requests, as the domain is not (yet) SSL-supported:</p>

<figure class='code'><figcaption><span></span></figcaption><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>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<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>
<span class='line-number'>24</span>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="c1">// static.json</span>
</span><span class='line'><span class="p">{</span>
</span><span class='line'>  <span class="s2">&quot;root&quot;</span><span class="o">:</span> <span class="s2">&quot;dist/&quot;</span><span class="p">,</span>
</span><span class='line'>  <span class="s2">&quot;https_only&quot;</span><span class="o">:</span> <span class="kc">false</span><span class="p">,</span>
</span><span class='line'>  <span class="s2">&quot;clean_urls&quot;</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span>
</span><span class='line'>  <span class="s2">&quot;routes&quot;</span><span class="o">:</span> <span class="p">{</span>
</span><span class='line'>    <span class="s2">&quot;/**&quot;</span><span class="o">:</span> <span class="s2">&quot;index.html&quot;</span>
</span><span class='line'>  <span class="p">},</span>
</span><span class='line'>  <span class="s2">&quot;headers&quot;</span><span class="o">:</span> <span class="p">{</span>
</span><span class='line'>    <span class="s2">&quot;/**&quot;</span><span class="o">:</span> <span class="p">{</span>
</span><span class='line'>      <span class="s2">&quot;Cache-Control&quot;</span><span class="o">:</span> <span class="s2">&quot;private, no-store, no-cache, must-revalidate, proxy-revalidate&quot;</span><span class="p">,</span>
</span><span class='line'>      <span class="s2">&quot;Pragma&quot;</span><span class="o">:</span> <span class="s2">&quot;no-cache&quot;</span><span class="p">,</span>
</span><span class='line'>      <span class="s2">&quot;Expires&quot;</span><span class="o">:</span> <span class="s2">&quot;Sat, 05 Nov 1955 00:00:00 PST&quot;</span><span class="p">,</span>
</span><span class='line'>      <span class="s2">&quot;Strict-Transport-Security&quot;</span><span class="o">:</span> <span class="s2">&quot;max-age=31536000; includeSubDomains;&quot;</span><span class="p">,</span>
</span><span class='line'>      <span class="s2">&quot;X-Download-Options&quot;</span><span class="o">:</span> <span class="s2">&quot;noopen&quot;</span><span class="p">,</span>
</span><span class='line'>      <span class="s2">&quot;X-Content-Type-Options&quot;</span><span class="o">:</span> <span class="s2">&quot;nosniff&quot;</span><span class="p">,</span>
</span><span class='line'>      <span class="s2">&quot;X-Frame-Options&quot;</span><span class="o">:</span> <span class="s2">&quot;SAMEORIGIN&quot;</span><span class="p">,</span>
</span><span class='line'>      <span class="s2">&quot;X-XSS-Protection&quot;</span><span class="o">:</span> <span class="s2">&quot;1; mode=block&quot;</span>
</span><span class='line'>    <span class="p">},</span>
</span><span class='line'>    <span class="s2">&quot;/assets/**&quot;</span><span class="o">:</span> <span class="p">{</span> <span class="s2">&quot;Cache-Control&quot;</span><span class="o">:</span> <span class="s2">&quot;public, max-age=512000&quot;</span> <span class="p">},</span>
</span><span class='line'>    <span class="s2">&quot;/robots.txt&quot;</span><span class="o">:</span> <span class="p">{</span> <span class="s2">&quot;Cache-Control&quot;</span><span class="o">:</span> <span class="s2">&quot;public, max-age=512000&quot;</span> <span class="p">},</span>
</span><span class='line'>    <span class="s2">&quot;/crossdomain.xml&quot;</span><span class="o">:</span> <span class="p">{</span> <span class="s2">&quot;Cache-Control&quot;</span><span class="o">:</span> <span class="s2">&quot;public, max-age=512000&quot;</span> <span class="p">}</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>This step is really only needed to change the default <code>https_only</code> setting. If
you have SSL set up for your domain, you don&#8217;t need the <code>static.json</code> file.</p>

<p>The next time I pushed to the remote set up by Heroku, it just worked, and my
app was now FastBoot enabled. Hooray!</p>

<h2>Acknowledgements and further resources</h2>

<p>I would like to thank <a href="https://twitter.com/abuiles">Adolfo</a> and <a href="https://twitter.com/rondale_sc">Jonathan</a> for their help in pointing
me at <a href="https://emberweekend.com/">Ember Weekend</a>, an Ember app that runs in FastBoot and <a href="https://github.com/ember-weekend/ember-weekend">whose source code is publicly available</a>,
and also for overcoming the above mentioned &#8220;missing dynamic content&#8221; problem.</p>

<p>My app does not use many of Fastboot&#8217;s features. If you&#8217;re looking to see a more
complex use case, check out the <a href="https://github.com/ember-weekend/ember-weekend">Ember Weekend source code</a>.</p>

<p>If you want to learn more about FastBoot&#8217;s architecture and rationale, I
recommend checking out <a href="https://vimeo.com/157688134">Tom Dale&#8217;s great presentation</a> he gave at Global
Ember Meetup.</p>

<p>Finally, the Rock and Roll demo app that this post describes is available on
Github at <a href="https://github.com/balinterdi/rarwe-demo">balinterdi/rarwe-demo</a> and deployed to <a href="http://demo.rockandrollwithemberjs.com">http://demo.rockandrollwithemberjs.com</a>.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Continuous Visual Integration for Ember apps]]></title>
    <link href="http://balinterdi.com/2016/10/17/continuous-visual-integration-for-ember-apps.html"/>
    <updated>2016-10-17T19:15:00+02:00</updated>
    <id>http://balinterdi.com/2016/10/17/continuous-visual-integration-for-ember-apps</id>
    <content type="html"><![CDATA[<p>I recently watched Mike Fotinakis&#8217;s presentation at the San Francisco Ember
meetup, <a href="https://youtu.be/iECnXK9EqA4">Continuous Visual Integration with Ember</a>,
and I&#8217;ve become really enthusiastic about visual diffs, and Percy.</p>

<p>It&#8217;s really worth the time and I highly recommend to watch it. I could say
&#8220;watch it now and then come back&#8221; but it&#8217;s a 50-minute long video while this
post takes 5 minutes to read, so I recommend to do it the other way around: read
this post first and then go and watch the presentation where he goes into more
details on what visual diffs and CI are, how Percy works and answers to
questions from the audience.</p>

<p>Ready? Cool. Start the timer and let&#8217;s go.</p>

<h3>So what is continuous visual integration?</h3>

<p>I will give you the high-level definition and rationale of visual diffs
and continuous visual integration as the post otherwise wouldn&#8217;t make sense.</p>

<p>When we change code, the intangible stuff apps are made of, we risk breaking it.
To prevent this, we write tests that guard against regression (a nice way of
saying breaking stuff) and do code reviews where someone goes over the code
diffs, and potentially after a series of edits, confirms it.</p>

<p>However, that&#8217;s just the code part. There are other ways to break a web
application, a major one among them is for the app to look differently than
before, in an unintended way. The background color of a button might change, a
link could have become hidden, or a css file could no longer be downloaded
which all lead to a degraded visual experience for visitors of the app.</p>

<p>Our (textual) tests could pass with flying colors and yet the users of the app
could be running away screaming from our site. Visual diffs guard against that
scenario by showing a visual diff, what certain scenarios looked before and
after the code changes under test.</p>

<h3>Visual diffs as part of the review process</h3>

<p>The idea is to have screenshots made at certain points in our user flows and
have a review process that approves the changes, just as we do for code.</p>

<p>To automate the process, we integrate the generation of visual diffing in the
automated testing process. This will produce the &#8220;before&#8221; and &#8220;after&#8221;
screenshots that will be used to generate the diffs. Let&#8217;s see how this is done
in practice.</p>

<h3>Making all this a breeze with Percy</h3>

<p>Percy is a visual diffing tool that automates all of this and integrates
smoothly into the Github pull request process. To get started with Percy,
install the Ember addon:</p>

<pre><code>$ ember install ember-percy
</code></pre>

<p>If you use Mirage for your tests, like I do, make sure to define a passthrough
rule for Percy on top of your Mirage config, before any other rules (see
<a href="https://percy.io/docs/clients/javascript/ember">the docs</a>):</p>

<figure class='code'><figcaption><span></span></figcaption><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='js'><span class='line'><span class="c1">// mirage/config.js</span>
</span><span class='line'><span class="kr">export</span> <span class="k">default</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>  <span class="k">this</span><span class="p">.</span><span class="nx">passthrough</span><span class="p">(</span><span class="s1">&#39;/_percy/**&#39;</span><span class="p">);</span>
</span><span class='line'>  <span class="p">(...)</span>
</span><span class='line'><span class="p">})</span>
</span></code></pre></td></tr></table></div></figure>


<p><strong>NOTE</strong> Starting from ember-percy version 1.2.4, you no longer need to do the
above as ember-percy doesn&#8217;t use Mirage anymore.</p>

<p>To demo how the development flow changes to accommodate visual diffing, I prepared <a href="https://github.com/balinterdi/rarwe-demo/pull/10">a PR to make a dropdown</a>
in the <a href="https://github.com/balinterdi/rarwe-demo">Rock and Roll with Ember demo</a> nicer.</p>

<p>Before implementing the change, I wrote a test that verifies if the songs for a
particular band are listed correctly:</p>

<figure class='code'><figcaption><span></span></figcaption><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>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<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>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="c1">// tests/acceptance/songs-test.js</span>
</span><span class='line'><span class="kr">import</span> <span class="nx">Ember</span> <span class="nx">from</span> <span class="s1">&#39;ember&#39;</span><span class="p">;</span>
</span><span class='line'><span class="kr">import</span> <span class="p">{</span> <span class="nx">test</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;qunit&#39;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="p">(...)</span>
</span><span class='line'>
</span><span class='line'><span class="nx">test</span><span class="p">(</span><span class="s1">&#39;List songs for a band&#39;</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">assert</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="nx">visit</span><span class="p">(</span><span class="s1">&#39;/bands&#39;</span><span class="p">);</span>
</span><span class='line'>  <span class="nx">click</span><span class="p">(</span><span class="s1">&#39;a:contains(&quot;Tool&quot;)&#39;</span><span class="p">);</span>
</span><span class='line'>  <span class="nx">percySnapshot</span><span class="p">(</span><span class="s1">&#39;list-songs-for-band&#39;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>  <span class="nx">andThen</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="nx">assert</span><span class="p">.</span><span class="nx">equal</span><span class="p">(</span><span class="nx">Ember</span><span class="p">.</span><span class="nx">$</span><span class="p">(</span><span class="s1">&#39;.song&#39;</span><span class="p">).</span><span class="nx">length</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="s2">&quot;All songs for the selected band are displayed&quot;</span><span class="p">);</span>
</span><span class='line'>    <span class="nx">assert</span><span class="p">.</span><span class="nx">equal</span><span class="p">(</span><span class="nx">Ember</span><span class="p">.</span><span class="nx">$</span><span class="p">(</span><span class="s1">&#39;.song:contains(&quot;46 &amp; 2&quot;)&#39;</span><span class="p">).</span><span class="nx">length</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="s2">&quot;The first song is displayed&quot;</span><span class="p">);</span>
</span><span class='line'>  <span class="p">});</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<p>The thing to note here is <code>percySnapshot</code>. If Percy is set up in the environment
where the test runs, it generates a screenshot identified by the name we pass it
(or auto-generates one). To set up Percy, the <code>PERCY_TOKEN</code> and <code>PERCY_PROJECT</code>
env vars need to be set in the CI tool of your choice. <a href="https://percy.io/docs">The Percy
docs</a> explain how.</p>

<p>Once we have a percySnapshot, the next time we push and our CI builds the
project, Percy will have a new snapshot for us:</p>

<p><img src="http://balinterdi.com/images/posts/visual-ci-with-percy/percy-first-screenshot.png" alt="First screenshot - No diff yet" /></p>

<p>We can now implement our feature on a branch and create a pull request for it on
Github. As you can see on the following screenshot, approving the visual diffs
is now part of the flow:</p>

<p><img src="http://balinterdi.com/images/posts/visual-ci-with-percy/github-pr-before-percy-approval.png" alt="Github before Percy approval" /></p>

<p>Clicking &#8220;Details&#8221; takes us to the visual diffs where we must explicilty approve
the changes:</p>

<p><img src="http://balinterdi.com/images/posts/visual-ci-with-percy/percy-visual-diff.png" alt="Percy visual diffs" /></p>

<p>Once the visual diffs are approved, the PR is all green and we can lean back in
our chairs and merge it, safe in the knowledge we did not visually break the
app.</p>

<p><img src="http://balinterdi.com/images/posts/visual-ci-with-percy/github-pr-after-percy-approval.png" alt="Github after Percy approval" /></p>

<p>Just as with &#8220;normal&#8221; tests, the more snapshots we have, the higher the chance
we did not introduce any regressions with our latest changes. Mike recommends a
&#8220;breadth first&#8221; approach, making screenshots from tests that verify different
scenarios instead of a &#8220;depth first&#8221; approach, creating several screenshots for
the same scenario.</p>

<h3>Closing words</h3>

<p>I&#8217;m all sold on visual diffing and I think there is tremendous value in securing
our apps this way.</p>

<p>I encourage you to <a href="https://youtu.be/iECnXK9EqA4">watch Mike&#8217;s presentation</a>
and <a href="https://percy.io/">sign up for Percy</a> to become a better steward of your applications.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Refactoring Promise Patterns]]></title>
    <link href="http://balinterdi.com/2016/10/05/refactoring-promise-patterns.html"/>
    <updated>2016-10-05T09:22:00+02:00</updated>
    <id>http://balinterdi.com/2016/10/05/refactoring-promise-patterns</id>
    <content type="html"><![CDATA[<p>I&#8217;m sure you have written a lot of code that looks something like this:</p>

<figure class='code'><figcaption><span></span></figcaption><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>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<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>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="c1">// app/controllers/band.js</span>
</span><span class='line'><span class="nx">actions</span><span class="o">:</span> <span class="p">{</span>
</span><span class='line'>  <span class="nx">save</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="kd">let</span> <span class="nx">band</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;model&#39;</span><span class="p">);</span>
</span><span class='line'>    <span class="k">this</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="s1">&#39;isLoading&#39;</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span>
</span><span class='line'>    <span class="k">return</span> <span class="nx">band</span><span class="p">.</span><span class="nx">save</span><span class="p">()</span>
</span><span class='line'>      <span class="p">.</span><span class="nx">then</span><span class="p">((</span><span class="nx">result</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">this</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="s1">&#39;successMessage&#39;</span><span class="p">,</span> <span class="s1">&#39;Band has been saved.&#39;</span><span class="p">);</span>
</span><span class='line'>      <span class="p">})</span>
</span><span class='line'>      <span class="p">.</span><span class="k">catch</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">this</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="s1">&#39;error&#39;</span><span class="p">,</span> <span class="s1">&#39;Band is too unruly to be saved.&#39;</span><span class="p">);</span>
</span><span class='line'>      <span class="p">})</span>
</span><span class='line'>      <span class="p">.</span><span class="k">finally</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">this</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="s1">&#39;isLoading&#39;</span><span class="p">,</span> <span class="kc">false</span><span class="p">);</span>
</span><span class='line'>      <span class="p">});</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Setting back <code>isLoading</code> to false is conveniently placed in a <code>finally</code> handler
so that it happens both if the promise resolves successfully (the band is
saved) and if it is rejected (there is an error during the save).</p>

<p>The <code>isLoading</code> is then used in the corresponding template to show a spinner
and/or disable the save button while the save is in flight:</p>

<div>
  <pre><code class='html'>// app/templates/band.hbs
&lt;button type=&quot;button&quot; onclick=(action &quot;save&quot;) disabled={{isLoading}}&gt;Save band&lt;/button&gt;</code></pre>
</div>


<p>I know I have written this hundreds of times by now and it has increasingly
disturbed me that setting and unsetting the loading flag is boilerplate code,
something that could be refactored.</p>

<p>One nice thing about promises is that they are easy to compose. Here is how
we could define a function that adds the boilerplatey parts:</p>

<figure class='code'><figcaption><span></span></figcaption><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>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<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>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="c1">// app/controllers/band.js</span>
</span><span class='line'>
</span><span class='line'><span class="kd">function</span> <span class="nx">saveWithLoadingFlag</span><span class="p">(</span><span class="nx">operation</span><span class="p">,</span> <span class="nx">loadingProperty</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="k">this</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="nx">loadingProperty</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span>
</span><span class='line'>  <span class="k">return</span> <span class="nx">operation</span><span class="p">.</span><span class="k">finally</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">this</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="nx">loadingProperty</span><span class="p">,</span> <span class="kc">false</span><span class="p">);</span>
</span><span class='line'>  <span class="p">});</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="nx">actions</span><span class="o">:</span> <span class="p">{</span>
</span><span class='line'>  <span class="nx">save</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="kd">let</span> <span class="nx">band</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;model&#39;</span><span class="p">);</span>
</span><span class='line'>    <span class="k">return</span> <span class="nx">saveWithLoadingFlag</span><span class="p">.</span><span class="nx">call</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="nx">band</span><span class="p">.</span><span class="nx">save</span><span class="p">(),</span> <span class="s1">&#39;isLoading&#39;</span><span class="p">)</span>
</span><span class='line'>      <span class="p">.</span><span class="nx">then</span><span class="p">((</span><span class="nx">result</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">this</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="s1">&#39;successMessage&#39;</span><span class="p">,</span> <span class="s1">&#39;Band has been saved.&#39;</span><span class="p">);</span>
</span><span class='line'>      <span class="p">})</span>
</span><span class='line'>      <span class="p">.</span><span class="k">catch</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">this</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="s1">&#39;error&#39;</span><span class="p">,</span> <span class="s1">&#39;Band is too unruly to be saved.&#39;</span><span class="p">);</span>
</span><span class='line'>      <span class="p">});</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>You might go a tiny step further and use a default value for the loading flag:</p>

<figure class='code'><figcaption><span></span></figcaption><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>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<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>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="c1">// app/controllers/band.js</span>
</span><span class='line'>
</span><span class='line'><span class="kd">function</span> <span class="nx">saveWithLoadingFlag</span><span class="p">(</span><span class="nx">operation</span><span class="p">,</span> <span class="nx">loadingProperty</span><span class="o">=</span><span class="s1">&#39;isLoading&#39;</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="k">this</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="nx">loadingProperty</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span>
</span><span class='line'>  <span class="k">return</span> <span class="nx">operation</span><span class="p">.</span><span class="k">finally</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">this</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="nx">loadingProperty</span><span class="p">,</span> <span class="kc">false</span><span class="p">);</span>
</span><span class='line'>  <span class="p">});</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="nx">actions</span><span class="o">:</span> <span class="p">{</span>
</span><span class='line'>  <span class="nx">save</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="kd">let</span> <span class="nx">band</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;model&#39;</span><span class="p">);</span>
</span><span class='line'>    <span class="k">return</span> <span class="nx">saveWithLoadingFlag</span><span class="p">.</span><span class="nx">call</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="nx">band</span><span class="p">.</span><span class="nx">save</span><span class="p">())</span>
</span><span class='line'>      <span class="p">.</span><span class="nx">then</span><span class="p">((</span><span class="nx">result</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">this</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="s1">&#39;successMessage&#39;</span><span class="p">,</span> <span class="s1">&#39;Band has been saved.&#39;</span><span class="p">);</span>
</span><span class='line'>      <span class="p">})</span>
</span><span class='line'>      <span class="p">.</span><span class="k">catch</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">this</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="s1">&#39;error&#39;</span><span class="p">,</span> <span class="s1">&#39;Band is too unruly to be saved.&#39;</span><span class="p">);</span>
</span><span class='line'>      <span class="p">});</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Since <code>saveWithLoadingFlag</code> returns a promise, we can add our own handlers to it,
including other <code>finally</code> handlers.</p>

<p>You can find a working example <a href="https://ember-twiddle.com/54db7a0a708afe3cf59bfa634f1c3a06?numColumns=2&amp;openFiles=controllers.application.js%2Ctemplates.application.hbs">here</a>,
where you can play around with it.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Rock and Roll with Ember.js 2.8 is released]]></title>
    <link href="http://balinterdi.com/2016/09/30/rock-and-roll-with-ember-dot-js-2-dot-8-is-released.html"/>
    <updated>2016-09-30T21:22:00+02:00</updated>
    <id>http://balinterdi.com/2016/09/30/rock-and-roll-with-ember-dot-js-2-dot-8-is-released</id>
    <content type="html"><![CDATA[<p>Yesterday I published an updated version of the <a href="http://rockandrollwithemberjs.com">Rock and Roll with Ember.js book</a>.
The app now runs on 2.8 (Ember CLI, Ember and Ember Data) and, as usual, there are a few other changes.</p>

<p>The biggest of these was updating the Deployment chapter.
<a href="https://www.pagefronthq.com/">PageFront</a> seems defunct so I replaced it with
<a href="https://surge.sh">Surge</a>. Above that I also updated the section on deploying
(to S3) with ember-cli-deploy as things have changed quite a bit.</p>

<p>You can check out the full list of changes <a href="https://github.com/balinterdi/rarwe-issues/milestone/16?closed=1">here</a>
or the book itself <a href="http://rockandrollwithemberjs.com">here.</a></p>

<hr />

<p><strong>PSA</strong>: Ember 2.9 will bring the long-awaited new rendering engine, <a href="http://emberjs.com/blog/2016/09/08/ember-2-8-and-2-9-beta-released.html">Glimmer 2</a>!</p>

<p>I already went ahead and updated the app to 2.9.beta to give it a whirl.</p>

<p>The results were pretty jaw-dropping:</p>

<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">My app.js size after upgrading the Rock and Roll <a href="https://twitter.com/hashtag/Ember?src=hash">#Ember</a> app to use Glimmer 2 (so from 2.8.1 to 2.9.0-beta.2) went from 233K to 79K 😮</p>&mdash; Balint Erdi (@baaz) <a href="https://twitter.com/baaz/status/776872893577822208">September 16, 2016</a></blockquote>


<script async src="http://balinterdi.com//platform.twitter.com/widgets.js" charset="utf-8"></script>


<p>I encourage you to <a href="http://emberjs.com/builds/#/beta">try switching your app to Glimmer 2</a> and see if you encounter any problems.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Rock and Roll with Ember.js 2.7 is released]]></title>
    <link href="http://balinterdi.com/2016/08/24/rock-and-roll-with-ember-dot-js-2-dot-7-is-released.html"/>
    <updated>2016-08-24T20:50:00+02:00</updated>
    <id>http://balinterdi.com/2016/08/24/rock-and-roll-with-ember-dot-js-2-dot-7-is-released</id>
    <content type="html"><![CDATA[<p>Today marks the release of the <a href="http://rockandrollwithemberjs.com">Rock and Roll with Ember.js book</a>,
version 2.7, which means the app built in the book now runs on Ember 2.7 (and uses Ember CLI 2.7).</p>

<p>There is a number of other small fixes, the full list of which you can see
<a href="https://github.com/balinterdi/rarwe-issues/milestone/15?closed=1">here</a>.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Using Dependency Injection to Write Better Tests]]></title>
    <link href="http://balinterdi.com/2016/08/11/using-dependency-injection-to-write-better-tests.html"/>
    <updated>2016-08-11T09:13:00+02:00</updated>
    <id>http://balinterdi.com/2016/08/11/using-dependency-injection-to-write-better-tests</id>
    <content type="html"><![CDATA[<p>Testing is given much emphasis in the Ember.js community, and testing tools have
showed steady progress to reduce the cost of writing tests of all types.</p>

<p>Lauren Tan wrote <a href="https://emberway.io/component-dependency-injection-in-ember-js-a46a39a5d30a#.45qfbv52x">a great post</a>
about how Dependency Injection (DI) can be used to decouple a parent component
from the internals of its child components. One of the gains of doing so is that
the parent component becomes more focused and thus easier to test.</p>

<p>In this post, I&#8217;m doing something similar, although much simpler. I want to show
you how to use DI in a simple helper function to make it easier to test.</p>

<h3>Just your ordinary, run-of-the-mill function</h3>

<p>Although the helper is an Ember (template) helper, the concepts could be very
easily transferred to other frameworks, libraries and even languages.</p>

<p>I recently had to modify a <code>normalizeText</code> helper function that looked
like this:</p>

<figure class='code'><figcaption><span></span></figcaption><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>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="c1">// tests/unit/helpers/normalize-text-test.js</span>
</span><span class='line'><span class="kr">import</span> <span class="nx">Ember</span> <span class="nx">from</span> <span class="s1">&#39;ember&#39;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="kr">export</span> <span class="kd">function</span> <span class="nx">normalizeText</span><span class="p">([</span><span class="nx">text</span><span class="p">])</span> <span class="p">{</span>
</span><span class='line'>  <span class="kd">let</span> <span class="nx">normalizedEOLs</span> <span class="o">=</span> <span class="nx">text</span><span class="p">.</span><span class="nx">trim</span><span class="p">().</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/(?:\r\n|\r|\n)/g</span><span class="p">,</span> <span class="s1">&#39;&lt;/p&gt;&lt;p&gt;&#39;</span><span class="p">);</span>
</span><span class='line'>  <span class="kd">let</span> <span class="nx">noEmptyParagraphs</span> <span class="o">=</span> <span class="nx">normalizedEOLs</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/(&lt;p&gt;&lt;\/p&gt;)/g</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">);</span>
</span><span class='line'>  <span class="k">return</span> <span class="nx">Ember</span><span class="p">.</span><span class="nb">String</span><span class="p">.</span><span class="nx">htmlSafe</span><span class="p">(</span><span class="s2">&quot;&lt;p&gt;&quot;</span> <span class="o">+</span> <span class="nx">noEmptyParagraphs</span> <span class="o">+</span> <span class="s2">&quot;&lt;/p&gt;&quot;</span><span class="p">);</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>(I realize the above code does not handle a text value of <code>undefined</code> or <code>null</code>.
The real code does but I want to keep the code examples to the minimum necessary
to get my point across.)</p>

<h3>Comparing objects to objects</h3>

<p>Its test was quite simple and straightforward:</p>

<figure class='code'><figcaption><span></span></figcaption><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>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="c1">// tests/unit/helpers/normalize-text-test.js</span>
</span><span class='line'><span class="kr">import</span> <span class="p">{</span> <span class="nx">normalizeText</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;../../../helpers/normalize-text&#39;</span><span class="p">;</span>
</span><span class='line'><span class="kr">import</span> <span class="p">{</span> <span class="nx">module</span><span class="p">,</span> <span class="nx">test</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;qunit&#39;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="nx">module</span><span class="p">(</span><span class="s1">&#39;Unit | Helper | normalize-text&#39;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'><span class="nx">test</span><span class="p">(</span><span class="s1">&#39;it works&#39;</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">assert</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="kd">let</span> <span class="nx">normalizedText</span> <span class="o">=</span> <span class="nx">normalizeText</span><span class="p">([</span><span class="s2">&quot;The brown fox\r\njumped over the quick rabbit.\n&quot;</span><span class="p">]);</span>
</span><span class='line'>  <span class="nx">assert</span><span class="p">.</span><span class="nx">equal</span><span class="p">(</span><span class="nx">normalizedText</span><span class="p">,</span> <span class="s2">&quot;&lt;p&gt;The brown fox&lt;/p&gt;&lt;p&gt;jumped over the quick rabbit.&lt;/p&gt;&quot;</span><span class="p">);</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<p>The problem with that test is that we compare two <code>Handlebars.SafeString</code>
instances (returned by <code>Ember.String.htmlSafe</code>) which are different even if
the strings they wrap, their value, is the same:</p>

<figure class='code'><figcaption><span></span></figcaption><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>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="kd">let</span> <span class="nx">s1</span> <span class="o">=</span> <span class="nx">Ember</span><span class="p">.</span><span class="nb">String</span><span class="p">.</span><span class="nx">htmlSafe</span><span class="p">(</span><span class="s2">&quot;sid transit gloria mundi&quot;</span><span class="p">);</span>
</span><span class='line'><span class="kd">let</span> <span class="nx">s2</span> <span class="o">=</span> <span class="nx">Ember</span><span class="p">.</span><span class="nb">String</span><span class="p">.</span><span class="nx">htmlSafe</span><span class="p">(</span><span class="s2">&quot;sid transit gloria mundi&quot;</span><span class="p">);</span>
</span><span class='line'><span class="nx">s1</span> <span class="o">===</span> <span class="nx">s2</span> <span class="c1">// =&gt; false</span>
</span></code></pre></td></tr></table></div></figure>


<p>We&#8217;re, however, interested in the equality of the strings. If only there was a
way to replace that pesky <code>Ember.String.htmlSafe</code> call from the call site&#8230;</p>

<h3>DI to the rescue</h3>

<p>This is exactly what Dependency Injection can help us do. Instead of hard-coding
that &#8220;sanitizer&#8221; function dependency, the function could take it as a parameter
so that callers could inject it. Usually DI examples use (and thus inject) class
names or object instances but it is important to realize that the injected param
could be very &#8220;primitive&#8221;, like a simple function.</p>

<p>So here is how I rewrote the function:</p>

<figure class='code'><figcaption><span></span></figcaption><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>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<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='js'><span class='line'><span class="c1">// app/helpers/normalize-text.js</span>
</span><span class='line'><span class="kr">import</span> <span class="nx">Ember</span> <span class="nx">from</span> <span class="s1">&#39;ember&#39;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="kr">export</span> <span class="kd">function</span> <span class="nx">normalizeText</span><span class="p">([</span><span class="nx">text</span><span class="p">],</span> <span class="nx">params</span><span class="o">=</span><span class="p">{})</span> <span class="p">{</span>
</span><span class='line'>  <span class="kd">let</span> <span class="p">{</span> <span class="nx">sanitizer</span><span class="o">=</span><span class="nx">Ember</span><span class="p">.</span><span class="nb">String</span><span class="p">.</span><span class="nx">htmlSafe</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">params</span><span class="p">;</span>
</span><span class='line'>  <span class="kd">let</span> <span class="nx">normalizedEOLs</span> <span class="o">=</span> <span class="nx">text</span><span class="p">.</span><span class="nx">trim</span><span class="p">().</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/(?:\r\n|\r|\n)/g</span><span class="p">,</span> <span class="s1">&#39;&lt;/p&gt;&lt;p&gt;&#39;</span><span class="p">);</span>
</span><span class='line'>  <span class="kd">let</span> <span class="nx">noEmptyParagraphs</span> <span class="o">=</span> <span class="nx">normalizedEOLs</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/(&lt;p&gt;&lt;\/p&gt;)/g</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">);</span>
</span><span class='line'>  <span class="k">return</span> <span class="nx">sanitizer</span><span class="p">(</span><span class="s2">&quot;&lt;p&gt;&quot;</span> <span class="o">+</span> <span class="nx">noEmptyParagraphs</span> <span class="o">+</span> <span class="s2">&quot;&lt;/p&gt;&quot;</span><span class="p">);</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="kr">export</span> <span class="k">default</span> <span class="nx">Ember</span><span class="p">.</span><span class="nx">Helper</span><span class="p">.</span><span class="nx">helper</span><span class="p">(</span><span class="nx">normalizeText</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>


<p>Notice how easy ES2015 destructuring makes the assignment of the sanitizer
function:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="kd">let</span> <span class="p">{</span> <span class="nx">sanitizer</span><span class="o">=</span><span class="nx">Ember</span><span class="p">.</span><span class="nb">String</span><span class="p">.</span><span class="nx">htmlSafe</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">params</span><span class="p">;</span>
</span></code></pre></td></tr></table></div></figure>


<p>If no <code>sanitizer</code> key was present in <code>params</code>, then it will have a value of
<code>Ember.String.htmlSafe</code>, the default behavior.</p>

<p>The call from the test can now override the default behavior of sending the
normalized text through <code>Ember.String.htmlSafe</code> by passing in a &#8220;no-op&#8221;
sanitizer function:</p>

<figure class='code'><figcaption><span></span></figcaption><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>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<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>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="c1">// tests/unit/helpers/normalize-text-test.js</span>
</span><span class='line'><span class="kr">import</span> <span class="p">{</span> <span class="nx">normalizeText</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;../../../helpers/normalize-text&#39;</span><span class="p">;</span>
</span><span class='line'><span class="kr">import</span> <span class="p">{</span> <span class="nx">module</span><span class="p">,</span> <span class="nx">test</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;qunit&#39;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="kd">function</span> <span class="nx">leaveAsIs</span><span class="p">(</span><span class="nx">text</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="k">return</span> <span class="nx">text</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="nx">module</span><span class="p">(</span><span class="s1">&#39;Unit | Helper | normalize-text&#39;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'><span class="nx">test</span><span class="p">(</span><span class="s1">&#39;it works&#39;</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">assert</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="kd">let</span> <span class="nx">normalizedText</span> <span class="o">=</span> <span class="nx">normalizeText</span><span class="p">([</span><span class="s2">&quot;The brown fox\r\njumped over the quick rabbit.\n&quot;</span><span class="p">],</span> <span class="p">{</span> <span class="nx">sanitizer</span><span class="o">:</span> <span class="nx">leaveAsIs</span> <span class="p">});</span>
</span><span class='line'>  <span class="nx">assert</span><span class="p">.</span><span class="nx">equal</span><span class="p">(</span><span class="nx">normalizedText</span><span class="p">,</span> <span class="s2">&quot;&lt;p&gt;The brown fox&lt;/p&gt;&lt;p&gt;jumped over the quick rabbit.&lt;/p&gt;&quot;</span><span class="p">);</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<p>We&#8217;re now comparing simple strings which place nicely with <code>assert.equal</code> (with
<code>===</code>), and our test now passes.</p>

<h3>Non-testing benefits</h3>

<p>Code modifications introduced for the sake of testing usually also improve the
non-testing aspect. Here, we made it possible to pass any function before we
return the normalized text. We could, for example, use this to replace the <code>&lt;p&gt;</code>
tags with <code>&lt;span&gt;</code>s, if we so wish.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Rock and Roll with Ember.js 2.6 is released]]></title>
    <link href="http://balinterdi.com/2016/07/07/rock-and-roll-with-ember-dot-js-2-dot-6-is-released.html"/>
    <updated>2016-07-07T22:21:00+02:00</updated>
    <id>http://balinterdi.com/2016/07/07/rock-and-roll-with-ember-dot-js-2-dot-6-is-released</id>
    <content type="html"><![CDATA[<p>With some delay, but I just sent an update to all of the Rock and Roll with
Ember.js customers. The book brings the app in sync with Ember, Ember Data and
Ember CLI 2.6. Among a few other improvments it:</p>

<ul>
<li>Makes sure the new Ember welcome page is removed before generating the
application template: <a href="https://github.com/balinterdi/rarwe-issues/issues/196">#196</a></li>
<li>Adds a version string to the book&#8217;s title and also in the Preface so that the
reader knows whether they are reading the latest version: <a href="https://github.com/balinterdi/rarwe-issues/issues/174">#174</a></li>
</ul>


<p>The list of all accomplished things can be seen <a href="https://github.com/balinterdi/rarwe-issues/milestone/14?closed=1">here</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Complex Component Design in Ember - Part 4 - Use the hash helper]]></title>
    <link href="http://balinterdi.com/2016/05/26/complex-component-design-in-ember-part-4-use-the-hash-helper.html"/>
    <updated>2016-05-26T09:21:00+02:00</updated>
    <id>http://balinterdi.com/2016/05/26/complex-component-design-in-ember-part-4-use-the-hash-helper</id>
    <content type="html"><![CDATA[<p><em>This is the fourth and final part of my Complex Component Design series. Here are the preceding posts:</em></p>

<ul>
<li><a href="http://balinterdi.com/2015/09/10/complex-component-design-in-ember-intro.html"><strong>Intro</strong></a></li>
<li><a href="http://balinterdi.com/2015/12/18/complex-components-in-ember-dot-js-part-1-analyzing-user-flows.html"><strong>Part 1 - Analyzing User Flows</strong></a></li>
<li><a href="http://balinterdi.com/2016/02/04/complex-components-in-ember-dot-js-part-2-towards-a-more-reactive-component.html"><strong>Part 2 - Towards a more reactive component</strong></a></li>
<li><a href="http://balinterdi.com/2016/04/08/complex-component-design-in-ember-replace-the-observer.html"><strong>Part 3 - Remove the observer</strong></a></li>
<li><strong>Part 4 - Use the hash helper</strong></li>
</ul>


<p>You can find the code for this post <a href="https://github.com/balinterdi/ember-cli-autocomplete/releases/tag/ccd-part-four">on Github.</a></p>

<hr />

<p>After our last refactoring, the <code>ember-cli-autocomplete</code> component no longer
uses observers. However, the list of parameters the outermost, container
component, <code>auto-complete</code> returns is now unwieldily long:</p>

<div>
  <pre><code class='html'>&lt;!-- tests/dummy/templates/index.hbs --&gt;
{{#auto-complete
          on-select=(action &quot;selectArtist&quot;)
          on-input=(action &quot;filterArtists&quot;)
          options=matchingArtists
          displayProperty=&quot;name&quot;
          class=&quot;autocomplete-container&quot; as |isDropdownOpen inputValue options
                                             focusedIndex selectedIndex
                                             toggleDropdown onSelect onInput|}}

  (...)
{{/auto-complete}}</code></pre>
</div>


<p>Not only does that look clumsy, it also makes refactoring more difficult and one
always constantly have to flip between the component&#8217;s template (where params
are yielded from) and the template where the component is used to see if the
position of values match. So how can improve this?</p>

<h2>Components as functions</h2>

<p>To understand several concepts about components, consider them functions.
Putting aside the fact that they can also emit DOM elements, you call them with
a list of arguments, usually, though not exclusively, a collection of key-value
pairs.  The component then does some internal stuff and returns a value from its
template via the <code>yield</code> keyword.</p>

<p>Our current case is another instance when treating them as functions can help us
find the solution. Ask yourself: what would you do if the return value of a
function you wrote grew to a long list of arguments? You would convert the
return value to a key-value collection, such as a hash, wouldn&#8217;t you?</p>

<p>Well, in Ember&#8217;s component land, we can do this by using the <code>hash</code> helper,
<a href="http://emberjs.com/blog/2016/01/15/ember-2-3-released.html">introduced in Ember 2.3</a>. It takes a list of key-value pairs at invocation
time and outputs an object (a hash) with them:</p>

<div>
  <pre><code class='html'>{{#with (hash firstName=&#39;Mike&#39; lastName=&#39;McCready&#39; instrument=&#39;guitar&#39;) as |musician|}}
  Hello, I&#39;m {{musician.firstName}} {{musician.lastName}} and I play the {{musician.instrument}}.
{{/with}}</code></pre>
</div>


<p>We can use the <code>hash</code> helper to bring some sanity to the return value of <code>auto-complete</code>
parameters. It currently looks like this:</p>

<div>
  <pre><code class='html'>&lt;!-- addon/templates/components/auto-complete.hbs --&gt;
{{yield isDropdownOpen
        inputValue
        options
        focusedIndex
        selectedIndex
        (action &quot;toggleDropdown&quot;)
        (action &quot;selectOption&quot;)
        (action &quot;inputDidChange&quot;)}}</code></pre>
</div>


<p>So we introduce the <code>hash</code> helper to get the following:</p>

<div>
  <pre><code class='html'>&lt;!-- addon/templates/components/auto-complete.hbs --&gt;
{{yield (hash
    isOpen=isDropdownOpen
    inputValue=inputValue
    options=options
    focusedIndex=focusedIndex
    selectedIndex=selectedIndex
    toggleDropdown=(action &quot;toggleDropdown&quot;)
    onSelect=(action &quot;selectItem&quot;)
    onInput=(action &quot;inputDidChange&quot;))}}</code></pre>
</div>


<h2>Modifying call sites</h2>

<p>Now that the component&#8217;s return value has changed, we should not forget to
modify the callers, the downstream components that use that value:</p>

<div>
  <pre><code class='html'>&lt;!-- tests/dummy/app/templates/index.hbs --&gt;
{{#auto-complete
      on-select=(action &quot;selectArtist&quot;)
      on-input=(action &quot;filterArtists&quot;)
      items=matchingArtists
      displayProperty=&quot;name&quot;
      class=&quot;autocomplete-container&quot; as |params|}}
  &lt;div class=&quot;input-group&quot;&gt;
    {{auto-complete-input
        value=params.inputValue
        on-change=params.onInput
        type=&quot;text&quot;
        class=&quot;combobox input-large form-control&quot;
        placeholder=&quot;Select an artist&quot;}}
    {{#auto-complete-list
        isVisible=params.isOpen
        class=&quot;typeahead typeahead-long dropdown-menu&quot;}}
      {{#each params.options as |option|}}
        {{#auto-complete-option
            index=option.index
            on-click=params.onSelect
            isFocused=(eq params.focusedIndex option.index)
            isSelected=(eq params.selectedIndex option.index)}}
          &lt;a href=&quot;#&quot;&gt;{{option.value}}&lt;/a&gt;
        {{/auto-complete-option}}
      {{else}}
        &lt;li&gt;&lt;a href=&quot;#&quot;&gt;No results.&lt;/a&gt;&lt;/li&gt;
      {{/each}}
    {{/auto-complete-list}}
    {{#auto-complete-dropdown-toggle on-click=params.toggleDropdown class=&quot;input-group-addon dropdown-toggle&quot;}}
      &lt;span class=&quot;caret&quot;&gt;&lt;/span&gt;
    {{/auto-complete-dropdown-toggle}}
  &lt;/div&gt;
{{/auto-complete}}</code></pre>
</div>


<p>Instead of the long list of parameters, <code>auto-complete</code> now yields a single hash
parameter (called <code>params</code> above), whose keys are used in the child components
(<code>params.isOpen</code>, <code>params.options</code>, etc.)</p>

<h2>Polyfill it</h2>

<p>Since we want our component to be usable not only in Ember >=2.3 applications,
where the <code>hash</code> helper is built in, we should add the
<code>ember-hash-helper-polyfill</code>, which makes the <code>hash</code> helper available in earlier
Ember versions, as a dependency of the addon:</p>

<figure class='code'><figcaption><span></span></figcaption><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>
<span class='line-number'>6</span>
<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='js'><span class='line'><span class="c1">// package.json</span>
</span><span class='line'><span class="p">{</span>
</span><span class='line'>  <span class="s2">&quot;name&quot;</span><span class="o">:</span> <span class="s2">&quot;ember-cli-autocomplete&quot;</span><span class="p">,</span>
</span><span class='line'>  <span class="s2">&quot;version&quot;</span><span class="o">:</span> <span class="s2">&quot;0.0.0&quot;</span><span class="p">,</span>
</span><span class='line'>  <span class="s2">&quot;dependencies&quot;</span><span class="o">:</span> <span class="p">{</span>
</span><span class='line'>    <span class="p">(...)</span>
</span><span class='line'>    <span class="s2">&quot;ember-hash-helper-polyfill&quot;</span><span class="o">:</span> <span class="s2">&quot;0.1.0&quot;</span>
</span><span class='line'>  <span class="p">},</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<h2>Wrapping up</h2>

<p>That wraps up my Complex Component Design in Ember.js series. Our component
improved by each post and I think we now have a pretty flexible and thus
reusable component. The main purpose of the series, however, is education, so I
hope that I was able to transfer some of the knowledge I&#8217;ve acquired by building
components.</p>

<p>If you would like to read the whole series as a pdf, just give my your email
address below and I&#8217;m sending it to you.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Rock and Roll with Ember.js 2.5 is released]]></title>
    <link href="http://balinterdi.com/2016/05/03/rock-and-roll-with-ember-dot-js-2-dot-5-is-released.html"/>
    <updated>2016-05-03T10:22:00+02:00</updated>
    <id>http://balinterdi.com/2016/05/03/rock-and-roll-with-ember-dot-js-2-dot-5-is-released</id>
    <content type="html"><![CDATA[<p>I published a new version of <a href="http://rockandrollwithemberjs.com">the Rock and Roll Ember.js book</a>, and the
related application. It now runs on Ember, Ember Data and Ember CLI ~2.5.0.</p>

<p>More importantly, I made other improvements that serve to improve clarity and
reduce the number of new things the reader has to absorb at each step, which I
think is hugely important for an efficient, non-frustrating learning process.</p>

<ol>
<li><p>The biggest change (and simplification) is that I no longer sort the songs
from the get-go. To do so, I needed to use the <code>SortableMixin</code> and later, when
that was gone, an <code>ArrayProxy</code>. This resulted in other simplifications, like
not having to use (and maintain) a jsbin for that code snippet that used the
&#8220;global&#8221; Ember application building style and iterated on the magical
<code>sortedContent</code> property.</p></li>
<li><p>I also improved the flow of the Components chapter, rearranged some sections,
explained a few things that help comprehension and moved a few things that
only add to the learning burden.</p></li>
<li><p>I created an Appendix, called &#8220;Encore&#8221; to further the rock analogy. I felt
(and got matching feedback) that on some occasions there were too many
&#8220;sidebar&#8221; explanations (called &#8220;Backstage&#8221; sections in the book), that either
weren&#8217;t important enough to warrant holding up the flow of explanation or
lacked context. I moved these sections into the Encore where interested
readers can learn about these topics when they see fit.</p></li>
<li><p>Last, but not least, I went through the book and built the application from
scratch to see that everything still works. I also applied git tags at the
end of each chapter so that readers of <a href="http://rockandrollwithemberjs.com/#light-my-fire">the middle-</a> and <a href="http://rockandrollwithemberjs.com/#stairway-to-heaven">high-tier packages</a>
can skip to each chapter in the code in a very simple way, using <code>git checkout</code>.</p></li>
</ol>


<p>(There were some other changes, the whole list of which you can see <a href="https://github.com/balinterdi/rarwe-issues/issues?q=is%3Aissue+milestone%3A2.5">here.</a>)</p>

<p>This is the most significant update since I published the Ember 2 version of the
book last October and I believe following the book (and the building of the app)
became even easier.</p>

<p>If this piqued your interest, you can download a sample chapter below.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Complex Component Design in Ember - Part 3 - Replace the observer]]></title>
    <link href="http://balinterdi.com/2016/04/08/complex-component-design-in-ember-replace-the-observer.html"/>
    <updated>2016-04-08T09:54:00+02:00</updated>
    <id>http://balinterdi.com/2016/04/08/complex-component-design-in-ember-replace-the-observer</id>
    <content type="html"><![CDATA[<p><em>This is part 3 of my Complex Component Design series. Here are the preceding posts:</em></p>

<ul>
<li><a href="http://balinterdi.com/2015/09/10/complex-component-design-in-ember-intro.html"><strong>Intro</strong></a></li>
<li><a href="http://balinterdi.com/2015/12/18/complex-components-in-ember-dot-js-part-1-analyzing-user-flows.html"><strong>Part 1 - Analyzing User Flows</strong></a></li>
<li><a href="http://balinterdi.com/2016/02/04/complex-components-in-ember-dot-js-part-2-towards-a-more-reactive-component.html"><strong>Part 2 - Towards a more reactive component</strong></a></li>
<li><strong>Part 3 - Replace the observer</strong></li>
<li><a href="http://balinterdi.com/2016/05/26/complex-component-design-in-ember-part-4-use-the-hash-helper.html"><strong>Part 4 - Use the hash helper</strong></a></li>
</ul>


<p>You can find the code for this post <a href="https://github.com/balinterdi/ember-cli-autocomplete/releases/tag/ccd-part-three">on Github.</a></p>

<hr />

<p>In the last post, we refactored towards a more reactive component and got
pretty far. However, we established that we&#8217;d still have to remove the observer
that was also causing a weird bug:</p>

<p><img src="http://balinterdi.com/images/posts/complex-component-design-ember/jpj-too-good-bug.gif" alt="JPJ is too good to be replaced" /></p>

<h3>Event origin and data owner components are different</h3>

<p>The reason we introduced an observer was that we wanted to trigger an action
when one of the options was selected via cycling through them and hitting the
return key on the focused option. Since the necessary data for that event was
contained in the <code>auto-complete-option</code> component but the source of the keyboard
event was the <code>auto-complete</code> component, we couldn&#8217;t simply trigger the action
with the right data from the event source.</p>

<p>We fixed this by using an observer so that even though the event that
should trigger the action was fired &#8220;upstream&#8221;, in the <code>auto-complete</code>
component, we could react to this change &#8220;downstream&#8221;, in the appropriate
<code>auto-complete-option</code> whose <code>isSelected</code> property became true:</p>

<figure class='code'><figcaption><span></span></figcaption><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>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<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>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="c1">// addon/components/auto-complete-option.js</span>
</span><span class='line'><span class="kr">import</span> <span class="nx">Ember</span> <span class="nx">from</span> <span class="s1">&#39;ember&#39;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="kr">export</span> <span class="k">default</span> <span class="nx">Ember</span><span class="p">.</span><span class="nx">Component</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span>
</span><span class='line'>  <span class="p">(...)</span>
</span><span class='line'>
</span><span class='line'>  <span class="nx">didBecomeSelected</span><span class="o">:</span> <span class="nx">Ember</span><span class="p">.</span><span class="nx">observer</span><span class="p">(</span><span class="s1">&#39;isSelected&#39;</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="kd">let</span> <span class="nx">isSelected</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;isSelected&#39;</span><span class="p">);</span>
</span><span class='line'>    <span class="k">if</span> <span class="p">(</span><span class="nx">isSelected</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>      <span class="k">this</span><span class="p">.</span><span class="nx">_selectItem</span><span class="p">();</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>  <span class="p">}),</span>
</span><span class='line'>
</span><span class='line'>   <span class="nx">_selectItem</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="kd">let</span> <span class="nx">item</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;item&#39;</span><span class="p">);</span>
</span><span class='line'>    <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;on-click&#39;</span><span class="p">)(</span><span class="nx">item</span><span class="p">,</span> <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;label&#39;</span><span class="p">));</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<p>Our analysis of the cause already hints at the solution. We could move the
knowledge of which option is selected up to the <code>auto-complete</code> component and
then, when the user hits the return key to select the focused option, trigger
the action with the data that we have at our disposal.</p>

<h3>Centralized power in auto-complete</h3>

<h4>Changes in components</h4>

<p>We will maintain the selected option in <code>auto-complete</code> and trigger the
<code>selectItem</code> action when one of them is selected via a return key event (I
skipped the code snippet that calls <code>selectOption</code> for return):</p>

<figure class='code'><figcaption><span></span></figcaption><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>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<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='js'><span class='line'><span class="c1">// addon/components/auto-complete.js</span>
</span><span class='line'><span class="kr">import</span> <span class="nx">Ember</span> <span class="nx">from</span> <span class="s1">&#39;ember&#39;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="kr">export</span> <span class="k">default</span> <span class="nx">Ember</span><span class="p">.</span><span class="nx">Component</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span>
</span><span class='line'>  <span class="p">(...)</span>
</span><span class='line'>  <span class="nx">selectOption</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="nx">event</span><span class="p">.</span><span class="nx">preventDefault</span><span class="p">();</span>
</span><span class='line'>    <span class="kr">const</span> <span class="nx">focusedIndex</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;focusedIndex&#39;</span><span class="p">);</span>
</span><span class='line'>    <span class="k">if</span> <span class="p">(</span><span class="nx">Ember</span><span class="p">.</span><span class="nx">isPresent</span><span class="p">(</span><span class="nx">focusedIndex</span><span class="p">))</span> <span class="p">{</span>
</span><span class='line'>      <span class="k">this</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="s1">&#39;selectedIndex&#39;</span><span class="p">,</span> <span class="nx">focusedIndex</span><span class="p">);</span>
</span><span class='line'>      <span class="k">this</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="s1">&#39;selectOption&#39;</span><span class="p">,</span> <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;selectedOption&#39;</span><span class="p">));</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>    <span class="k">this</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="s1">&#39;isDropdownOpen&#39;</span><span class="p">,</span> <span class="kc">false</span><span class="p">);</span>
</span><span class='line'>  <span class="p">},</span>
</span><span class='line'>
</span><span class='line'>  <span class="nx">selectedOption</span><span class="o">:</span> <span class="nx">Ember</span><span class="p">.</span><span class="nx">computed</span><span class="p">(</span><span class="s1">&#39;selectedIndex&#39;</span><span class="p">,</span> <span class="s1">&#39;options.[]&#39;</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;options&#39;</span><span class="p">).</span><span class="nx">objectAt</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;selectedIndex&#39;</span><span class="p">));</span>
</span><span class='line'>  <span class="p">}),</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<p>On line 11, we call the <code>selectOption</code> action (renamed from <code>selectItem</code>) with
the (new) selected option. <code>selectedOption</code> is simply the option that has the
<code>selectedIndex</code>.</p>

<p>Independently of the current <code>selectOption</code> refactor, let&#8217;s fix a nasty
bug by making sure to reset the <code>focusedIndex</code> when the input changes:</p>

<figure class='code'><figcaption><span></span></figcaption><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>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<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>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="c1">// addon/components/auto-complete.js</span>
</span><span class='line'><span class="kr">import</span> <span class="nx">Ember</span> <span class="nx">from</span> <span class="s1">&#39;ember&#39;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="kr">export</span> <span class="k">default</span> <span class="nx">Ember</span><span class="p">.</span><span class="nx">Component</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span>
</span><span class='line'>  <span class="p">(...)</span>
</span><span class='line'>  <span class="nx">actions</span><span class="o">:</span> <span class="p">{</span>
</span><span class='line'>    <span class="nx">inputDidChange</span><span class="p">(</span><span class="nx">value</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>      <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;on-input&#39;</span><span class="p">)(</span><span class="nx">value</span><span class="p">);</span>
</span><span class='line'>      <span class="k">this</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="s1">&#39;focusedIndex&#39;</span><span class="p">,</span> <span class="kc">null</span><span class="p">);</span>
</span><span class='line'>      <span class="p">(...)</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<p>Next, let&#8217;s look at how the <code>selectOption</code> action needs to change:</p>

<figure class='code'><figcaption><span></span></figcaption><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>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<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>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="c1">// addon/components/auto-complete.js</span>
</span><span class='line'><span class="kr">import</span> <span class="nx">Ember</span> <span class="nx">from</span> <span class="s1">&#39;ember&#39;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="kr">export</span> <span class="k">default</span> <span class="nx">Ember</span><span class="p">.</span><span class="nx">Component</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span>
</span><span class='line'>  <span class="p">(...)</span>
</span><span class='line'>  <span class="nx">_displayForOption</span><span class="p">(</span><span class="nx">option</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="kr">const</span> <span class="nx">displayProperty</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;displayProperty&#39;</span><span class="p">);</span>
</span><span class='line'>    <span class="k">return</span> <span class="nx">option</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="nx">displayProperty</span><span class="p">);</span>
</span><span class='line'>  <span class="p">},</span>
</span><span class='line'>
</span><span class='line'>  <span class="nx">actions</span><span class="o">:</span> <span class="p">{</span>
</span><span class='line'>    <span class="nx">selectOption</span><span class="p">(</span><span class="nx">option</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>      <span class="kd">let</span> <span class="nx">inputValue</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">_displayForOption</span><span class="p">(</span><span class="nx">option</span><span class="p">);</span>
</span><span class='line'>      <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;on-select&#39;</span><span class="p">)(</span><span class="nx">option</span><span class="p">);</span>
</span><span class='line'>      <span class="k">this</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="s1">&#39;isDropdownOpen&#39;</span><span class="p">,</span> <span class="kc">false</span><span class="p">);</span>
</span><span class='line'>      <span class="k">this</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="s1">&#39;inputValue&#39;</span><span class="p">,</span> <span class="nx">inputValue</span><span class="p">);</span>
</span><span class='line'>    <span class="p">},</span>
</span><span class='line'>    <span class="p">(...)</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<p>One of the things that has changed is that it now only receives one argument,
<code>option</code> as the label of the option can now be computed internally, from within
the component.</p>

<p>That means that the label now does not need to be passed to the
<code>auto-complete-option</code> components and that its action that gets triggered when
the user clicks on it needs to be adjusted:</p>

<figure class='code'><figcaption><span></span></figcaption><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>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<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>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="c1">// addon/components/auto-complete-option.js</span>
</span><span class='line'><span class="kr">import</span> <span class="nx">Ember</span> <span class="nx">from</span> <span class="s1">&#39;ember&#39;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="kr">export</span> <span class="k">default</span> <span class="nx">Ember</span><span class="p">.</span><span class="nx">Component</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span>
</span><span class='line'>  <span class="nx">tagName</span><span class="o">:</span> <span class="s1">&#39;li&#39;</span><span class="p">,</span>
</span><span class='line'>  <span class="nx">classNames</span><span class="o">:</span> <span class="s1">&#39;ember-autocomplete-option&#39;</span><span class="p">,</span>
</span><span class='line'>  <span class="nx">classNameBindings</span><span class="o">:</span> <span class="nx">Ember</span><span class="p">.</span><span class="nb">String</span><span class="p">.</span><span class="nx">w</span><span class="p">(</span><span class="s1">&#39;isSelected:active isFocused:focused&#39;</span><span class="p">),</span>
</span><span class='line'>
</span><span class='line'>  <span class="nx">item</span><span class="o">:</span> <span class="kc">null</span><span class="p">,</span>
</span><span class='line'>  <span class="s1">&#39;on-click&#39;</span><span class="o">:</span> <span class="kc">null</span><span class="p">,</span>
</span><span class='line'>  <span class="nx">isFocused</span><span class="o">:</span> <span class="kc">false</span><span class="p">,</span>
</span><span class='line'>  <span class="nx">isSelected</span><span class="o">:</span> <span class="kc">false</span><span class="p">,</span>
</span><span class='line'>
</span><span class='line'>  <span class="nx">click</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;on-click&#39;</span><span class="p">)(</span><span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;item&#39;</span><span class="p">));</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<p>You can see I removed the observer and that I only send the item (not the label,
see the very first code example) in the action handler to comply with the new
API of the <code>selectOption</code> action.</p>

<h4>Changes in templates</h4>

<p>Let&#8217;s see how the templates need to change to accommodate that change.</p>

<p>First of all, the template of the <code>auto-complete</code> component needs to yield the
<code>options</code> to be consumed downstream. Let&#8217;s also not forget to rename
<code>selectItem</code> to <code>selectOption</code>:</p>

<div>
  <pre><code class='html'>&lt;!-- addon/templates/components/auto-complete.hbs --&gt;
{{yield isDropdownOpen
        inputValue
        options
        focusedIndex
        selectedIndex
        (action &quot;toggleDropdown&quot;)
        (action &quot;selectOption&quot;)
        (action &quot;inputDidChange&quot;)}}</code></pre>
</div>


<p>Then, the <code>each</code> loop should iterate through <code>options</code>, and not through
<code>matchingArtists</code> as before:</p>

<div>
  <pre><code class='html'>&lt;!-- tests/dummy/app/templates/index.hbs --&gt;
{{#auto-complete
      on-select=(action &quot;selectArtist&quot;)
      on-input=(action &quot;filterArtists&quot;)
      options=matchingArtists
      displayProperty=&quot;name&quot;
      class=&quot;autocomplete-container&quot; as |isDropdownOpen inputValue options
                                         focusedIndex selectedIndex
                                         toggleDropdown onSelect onInput|}}
  &lt;div class=&quot;input-group&quot;&gt;
    {{auto-complete-input
        value=inputValue
        on-change=onInput
        type=&quot;text&quot;
        class=&quot;combobox input-large form-control&quot;
        placeholder=&quot;Select an artist&quot;}}
    {{#auto-complete-list
        isVisible=isDropdownOpen
        class=&quot;typeahead typeahead-long dropdown-menu&quot;}}
      {{#each options as |option index|}}
        {{#auto-complete-option
            item=option
            on-click=onSelect
            isFocused=(eq focusedIndex index)
            isSelected=(eq selectedIndex index)}}
          &lt;a href=&quot;#&quot;&gt;{{option.name}}&lt;/a&gt;
        {{/auto-complete-option}}
      {{else}}
        &lt;li&gt;&lt;a href=&quot;#&quot;&gt;No results.&lt;/a&gt;&lt;/li&gt;
      {{/each}}
    {{/auto-complete-list}}
    {{#auto-complete-dropdown-toggle on-click=toggleDropdown class=&quot;input-group-addon dropdown-toggle&quot;}}
      &lt;span class=&quot;caret&quot;&gt;&lt;/span&gt;
    {{/auto-complete-dropdown-toggle}}
  &lt;/div&gt;
{{/auto-complete}}</code></pre>
</div>


<p>The bug at the beginning of the post is now gone:</p>

<p><img src="http://balinterdi.com/images/posts/complex-component-design-ember/jpj-too-good-to-go-fixed.gif" alt="JPG too-good-to-go bug fixed" /></p>

<h3>In the next episode&#8230;</h3>

<p>We now have a working, state-of-the-art component design with no coupling
between the sub-components and no observers. One thing that is not ideal,
though, is the number of parameters the <code>auto-complete</code> components yields (see
last code snippet).</p>

<p>Just as you wouldn&#8217;t have a method with 7 or 8 positional parameters, you don&#8217;t
want a component that yields that many properties matched by position. So in the
next installment of this series, we&#8217;ll use the <code>hash</code> helper to transform that
long list into keyed parameters.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Rock and Roll with Ember.js - Now on 2.4 and with code diffs]]></title>
    <link href="http://balinterdi.com/2016/03/24/rock-and-roll-with-ember-dot-js-now-on-2-dot-4-and-with-code-diffs.html"/>
    <updated>2016-03-24T15:12:00+01:00</updated>
    <id>http://balinterdi.com/2016/03/24/rock-and-roll-with-ember-dot-js-now-on-2-dot-4-and-with-code-diffs</id>
    <content type="html"><![CDATA[<p>I have just sent an updated version of Rock and Roll with Ember.js to my
readers. <a href="http://rockandrollwithemberjs.com">The app</a> now runs on Ember 2.4.3.</p>

<p>The biggest change in this release is that I now leverage code diffs in code
snippets, where this makes understanding changes easier. It looks like this in
the pdf version:</p>

<p><img src="http://balinterdi.com/images/posts/rarwe-2-4-released/code-diff-example.png" alt="Colored code diffs" /></p>

<p>Since the last release was more than two months ago and I constantly improve
things, there is a whole slew of other changes that you can see <a href="https://github.com/balinterdi/rarwe-issues/issues?q=is%3Aissue+milestone%3A2.4+is%3Aclosed">here</a>.</p>

<p>If you are not yet a reader yet and want to have an always up-to-date Ember
guide book, sign up below to get a sample chapter:</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Rock and Roll with Ember.js demo - A public Ember.js example project]]></title>
    <link href="http://balinterdi.com/2016/02/26/rock-and-roll-with-ember-dot-js-demo-a-public-ember-dot-js-example-project.html"/>
    <updated>2016-02-26T11:04:00+01:00</updated>
    <id>http://balinterdi.com/2016/02/26/rock-and-roll-with-ember-dot-js-demo-a-public-ember-dot-js-example-project</id>
    <content type="html"><![CDATA[<p>I have a book called Rock and Roll with Ember.js that has an accompanying
application we develop throughout the book. I also maintain a demo version of
the same app which has been open-source since its inception. However, that demo app
has not received updates for a while now so I decided to do something about
this and spent some time this week on making it a state-of-the-art Ember 2 application.</p>

<p>Here are the main developments I have made:</p>

<ul>
<li><strong>Upgraded it to use the latest Ember, Ember Data and Ember CLI versions, 2.3.0.</strong></li>
<li><strong>Used <a href="http://www.ember-cli-mirage.com/">ember-cli-mirage</a> to seed the app with data and handle &#8220;backend&#8221; requests.</strong>
(Look, ma&#8217;, no backend!)
<a href="http://www.ember-cli-mirage.com/">ember-cli-mirage</a> is fantastic addon that lets you set up route handlers,
fixtures, factories and many more to manage your seed data and mock your server
responses, both in development and tests. This was the first time I seriously
used it and I have grown to like it a ton! The author, <a href="https://twitter.com/samselikoff">Sam Selikoff</a>, helped
out tremendously and had an amazing turnaround on a few questions/issues.
I used the latest beta version, 0.2.0-beta.7, which you should definitely
check out and give feedback to Sam.</li>
<li><strong>Made it a modern, idiomatic Ember app.</strong>
It&#8217;s not just Ember, but also Javascript that evolves at a neck-breaking space
(although to a lesser extent). I used the not-at-all elementary
<a href="https://github.com/abuiles/ember-watson">ember-watson</a> to modernize the Ember app and applied a few manual tweaks
for some of the Javascript parts, like using destructuring and <code>let</code> and <code>const</code>
instead of <code>var</code>.</li>
<li><strong>Deployed it to be publicly accessible.</strong>
Leveraging the most excellent <a href="https://www.pagefronthq.com/">PageFront</a>, the app is now deployed to their
platform. You can see it in action at <a href="https://rarwe-demo.pagefrontapp.com/">https://rarwe-demo.pagefrontapp.com</a>.
This was not even a task, I only needed to issue two commands, one to install
the add-on and one to deploy it.</li>
</ul>


<p>The source lives on Github, at <a href="https://github.com/balinterdi/rarwe-demo">balinterdi/rarwe-demo</a>.</p>

<p>As Mirage can also be used in production (although it&#8217;s probably not common to
do that), you can check out <a href="https://rarwe-demo.pagefrontapp.com/">the &#8220;production&#8221; app</a>, with the same seed data I
used in development, and play around with it.</p>

<p>As I mentioned in the introduction, the full version of the app is developed
chapter by chapter in <a href="http://rockandrollwithemberjs.com">the Rock and Roll with Ember book</a>. You can download a
sample chapter below:</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[How to make an Ember module resolve as another one]]></title>
    <link href="http://balinterdi.com/2016/02/12/how-to-make-an-ember-module-resolve-as-another-one.html"/>
    <updated>2016-02-12T11:12:00+01:00</updated>
    <id>http://balinterdi.com/2016/02/12/how-to-make-an-ember-module-resolve-as-another-one</id>
    <content type="html"><![CDATA[<p>I wanted to write another short, and hopefully useful, post just as I did
recently for <a href="http://balinterdi.com/2016/02/03/binding-style-attributes-warning-in-ember.html">binding the style attribute</a>.</p>

<h2>No configuration is simpler than no configuration</h2>

<p>About a month ago I was working to add authorization to the <a href="http://rockandrollwithemberjs.com">Rock and Roll with
Ember</a> application. I used my favorite addon, <a href="https://github.com/Vestorly/torii">Torii</a>, to help with that
and opted to do the authorization via the <code>google-oauth2-bearer</code> provider.  To
restore the session, Torii looks up the application (Torii) adapter, but the
session initialization and closing code used the <code>google-oauth2-bearer</code>
adapter. So I had two separate files, which I was not happy about and I did not
want to merge everything into the <code>application</code> adapter, as it does not give a
hint about its contents then.</p>

<p>My idea was to make it possible to use another adapter <a href="https://github.com/Vestorly/torii/issues/268">to restore the session
from, via a configuration option</a>. Matthew Beale hinted at a solution that
removes the need for a configuration option and since I haven&#8217;t seen this
before, I want to share it with you.</p>

<h2>Import from target module, then reexport</h2>

<p>The Ember resolver is the piece that maps qualified full names (like
<code>route:blog</code> or <code>controller:bands</code>) to module names.</p>

<p>In my case, Torii makes the resolver look up <code>torii-adapter:application</code> to
fetch the session from and I wanted this to be resolved to
<code>torii-adapter:google-oauth2-bearer</code>. In the Ember CLI project, that is
equivalent of having the <code>app/torii-adapters/application.js</code> file export
what is exported by <code>app/torii-adapters/google-oauth2-bearer.js</code>.</p>

<p>When phrased like this, the solution is near and I am somewhat embarrassed it
took me a few attempts to arrive at this.</p>

<p>So the solution is to import in <code>app/torii-adapters/application.js</code> what
<code>app/torii-adapters/google-oauth2-bearer.js</code> exports and then reexport it:</p>

<figure class='code'><figcaption><span></span></figcaption><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>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="c1">// app/torii-adapters/application.js</span>
</span><span class='line'><span class="kr">import</span> <span class="nx">GoogleOAuth2BearerAdapter</span> <span class="nx">from</span> <span class="s1">&#39;./google-oauth2-bearer&#39;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="kr">export</span> <span class="k">default</span> <span class="nx">GoogleOAuth2BearerAdapter</span><span class="p">;</span>
</span></code></pre></td></tr></table></div></figure>




<figure class='code'><figcaption><span></span></figcaption><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>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="c1">// app/torii-adapters/google-oauth2-bearer.js</span>
</span><span class='line'><span class="kr">export</span> <span class="k">default</span> <span class="nx">Ember</span><span class="p">.</span><span class="nb">Object</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span>
</span><span class='line'>  <span class="p">(...)</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<p>Voila, we have &#8220;tricked&#8221; the resolver without adding any configuration
(and thus complexity) to the addon.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Complex Components in Ember.js - Part 2 - Towards a more reactive component]]></title>
    <link href="http://balinterdi.com/2016/02/04/complex-components-in-ember-dot-js-part-2-towards-a-more-reactive-component.html"/>
    <updated>2016-02-04T08:11:00+01:00</updated>
    <id>http://balinterdi.com/2016/02/04/complex-components-in-ember-dot-js-part-2-towards-a-more-reactive-component</id>
    <content type="html"><![CDATA[<p><em>This is part 2 of my Complex Component Design series. Here are the posts in the series:</em></p>

<ul>
<li><a href="http://balinterdi.com/2015/09/10/complex-component-design-in-ember-intro.html"><strong>Intro</strong></a></li>
<li><a href="http://balinterdi.com/2015/12/18/complex-components-in-ember-dot-js-part-1-analyzing-user-flows.html"><strong>Part 1 - Analyzing User Flows</strong></a></li>
<li><strong>Part 2 - Towards a more reactive component</strong></li>
<li><a href="http://balinterdi.com/2016/04/08/complex-component-design-in-ember-replace-the-observer.html"><strong>Part 3 - Remove the observer</strong></a></li>
<li><a href="http://balinterdi.com/2016/05/26/complex-component-design-in-ember-part-4-use-the-hash-helper.html"><strong>Part 4 - Use the hash helper</strong></a></li>
</ul>


<hr />

<p>In <a href="http://balinterdi.com/2015/12/18/complex-components-in-ember-dot-js-part-1-analyzing-user-flows.html">the previous part of this series</a>, the implementation of the main user
flows were explained in detail. I ended the post by saying that I was not
content with the implementation for several reasons, the most crucial of which
was that parent components needed to be passed down to children, so that
children can register themselves with their parent. That, in turn, allowed
parents to reach their children and call methods on them directly instead of
using events, actions and data bindings for communication. In this post, we&#8217;ll
see how to get rid of these and replace them with more reactive solutions.</p>

<h2>Remove the need for direct access to the input</h2>

<p>Currently, the autocomplete component (the parent) yields itself to its
children. <code>auto-complete-input</code> binds its own <code>autocomplete</code> attribute to it so
that it can register itself with its parent when inserted:</p>

<div>
  <pre><code class='html'>&lt;!-- tests/dummy/app/templates/index.hbs --&gt;
{{#auto-complete
      on-select=(action &quot;selectArtist&quot;)
      on-input=(action &quot;filterArtists&quot;)
      class=&quot;autocomplete-container&quot; as
        |autocomplete isDropdownOpen inputValue
         toggleDropdown onSelect onInput|}}
  &lt;div class=&quot;input-group&quot;&gt;
    {{auto-complete-input
        autocomplete=autocomplete
        value=inputValue
        on-change=onInput
        type=&quot;text&quot;
        class=&quot;combobox input-large form-control&quot;
        placeholder=&quot;Select an artist&quot;}}
    (...)
  &lt;/div&gt;
(...)
{{/auto-complete}}</code></pre>
</div>




<figure class='code'><figcaption><span></span></figcaption><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>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<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='js'><span class='line'><span class="c1">// addon/components/auto-complete-input.js</span>
</span><span class='line'><span class="kr">import</span> <span class="nx">Ember</span> <span class="nx">from</span> <span class="s1">&#39;ember&#39;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="kr">export</span> <span class="k">default</span> <span class="nx">Ember</span><span class="p">.</span><span class="nx">TextField</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span>
</span><span class='line'>  <span class="nx">autocomplete</span><span class="o">:</span> <span class="kc">null</span><span class="p">,</span>
</span><span class='line'>
</span><span class='line'>  <span class="nx">registerWithAutocomplete</span><span class="o">:</span> <span class="nx">Ember</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">&#39;didInsertElement&#39;</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;autocomplete&#39;</span><span class="p">).</span><span class="nx">registerInput</span><span class="p">(</span><span class="k">this</span><span class="p">);</span>
</span><span class='line'>  <span class="p">}),</span>
</span><span class='line'>  <span class="p">(...)</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<p>This is needed when the item is autocompleted and the autocompleted segment is
pre-selected so that the user can type over it if it&#8217;s not the item they had in
mind:</p>

<figure class='code'><figcaption><span></span></figcaption><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>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<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>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="c1">// addon/components/auto-complete.js</span>
</span><span class='line'><span class="kr">export</span> <span class="k">default</span> <span class="nx">Ember</span><span class="p">.</span><span class="nx">Component</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span>
</span><span class='line'>  <span class="p">(...)</span>
</span><span class='line'>  <span class="nx">actions</span><span class="o">:</span> <span class="p">{</span>
</span><span class='line'>    <span class="nx">inputDidChange</span><span class="p">(</span><span class="nx">value</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>      <span class="p">(...)</span>
</span><span class='line'>      <span class="nx">Ember</span><span class="p">.</span><span class="nx">run</span><span class="p">.</span><span class="nx">scheduleOnce</span><span class="p">(</span><span class="s1">&#39;afterRender&#39;</span><span class="p">,</span> <span class="k">this</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>        <span class="p">(...)</span>
</span><span class='line'>        <span class="kr">const</span> <span class="nx">firstOption</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;list.firstOption&#39;</span><span class="p">);</span>
</span><span class='line'>        <span class="k">if</span> <span class="p">(</span><span class="nx">firstOption</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>          <span class="kr">const</span> <span class="nx">autocompletedLabel</span> <span class="o">=</span> <span class="nx">firstOption</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;label&#39;</span><span class="p">);</span>
</span><span class='line'>          <span class="k">this</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="s1">&#39;focusedOption&#39;</span><span class="p">,</span> <span class="nx">firstOption</span><span class="p">);</span>
</span><span class='line'>          <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;on-select&#39;</span><span class="p">)(</span><span class="nx">firstOption</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;item&#39;</span><span class="p">));</span>
</span><span class='line'>          <span class="k">this</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="s1">&#39;inputValue&#39;</span><span class="p">,</span> <span class="nx">autocompletedLabel</span><span class="p">);</span>
</span><span class='line'>          <span class="nx">Ember</span><span class="p">.</span><span class="nx">run</span><span class="p">.</span><span class="nx">next</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>            <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;input.element&#39;</span><span class="p">).</span><span class="nx">setSelectionRange</span><span class="p">(</span><span class="nx">value</span><span class="p">.</span><span class="nx">length</span><span class="p">,</span> <span class="nx">autocompletedLabel</span><span class="p">.</span><span class="nx">length</span><span class="p">);</span>
</span><span class='line'>          <span class="p">});</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>      <span class="p">});</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<p>On the very last line, the component accesses the <code>input</code> directly, to select
(and highlight) the portion of the item that was autocompleted. That&#8217;s why we
need the whole registration process.</p>

<p>Since <code>inputDidChange</code> is triggered from the <code>auto-complete-input</code> component, we
could get rid of this direct coupling if there was a way to react to the
action&#8217;s result in the <code>auto-complete-input</code> itself. That way is called closure
actions.</p>

<h3>Fire, but don&#8217;t forget</h3>

<p>As opposed to the fire-and-forget nature of &#8220;ordinary&#8221; (aka. element) actions,
closure actions provide a way to react to the action&#8217;s outcome at the source,
where the action was fired from.</p>

<p>Since closure actions are functions, they can have return values. If the action
triggers an async action, it&#8217;s best to return a promise from the upstream
handler to which the event source can attach its handler to.</p>

<p>Let&#8217;s see how that works in our case.</p>

<figure class='code'><figcaption><span></span></figcaption><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>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<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>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="c1">// addon/components/auto-complete.js</span>
</span><span class='line'><span class="kr">export</span> <span class="k">default</span> <span class="nx">Ember</span><span class="p">.</span><span class="nx">Component</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span>
</span><span class='line'>  <span class="p">(...)</span>
</span><span class='line'>  <span class="nx">actions</span><span class="o">:</span> <span class="p">{</span>
</span><span class='line'>    <span class="nx">inputDidChange</span><span class="p">(</span><span class="nx">value</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>      <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;on-input&#39;</span><span class="p">)(</span><span class="nx">value</span><span class="p">);</span>
</span><span class='line'>      <span class="k">this</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="s1">&#39;isDropdownOpen&#39;</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span>
</span><span class='line'>      <span class="k">return</span> <span class="k">new</span> <span class="nx">Ember</span><span class="p">.</span><span class="nx">RSVP</span><span class="p">.</span><span class="nx">Promise</span><span class="p">((</span><span class="nx">resolve</span><span class="p">,</span> <span class="nx">reject</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>        <span class="p">(...)</span>
</span><span class='line'>        <span class="nx">Ember</span><span class="p">.</span><span class="nx">run</span><span class="p">.</span><span class="nx">scheduleOnce</span><span class="p">(</span><span class="s1">&#39;afterRender&#39;</span><span class="p">,</span> <span class="k">this</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>          <span class="kr">const</span> <span class="nx">firstOption</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;list.firstOption&#39;</span><span class="p">);</span>
</span><span class='line'>          <span class="k">if</span> <span class="p">(</span><span class="nx">firstOption</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>            <span class="kr">const</span> <span class="nx">autocompletedLabel</span> <span class="o">=</span> <span class="nx">firstOption</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;label&#39;</span><span class="p">);</span>
</span><span class='line'>            <span class="k">this</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="s1">&#39;focusedOption&#39;</span><span class="p">,</span> <span class="nx">firstOption</span><span class="p">);</span>
</span><span class='line'>            <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;on-select&#39;</span><span class="p">)(</span><span class="nx">firstOption</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;item&#39;</span><span class="p">));</span>
</span><span class='line'>            <span class="k">this</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="s1">&#39;inputValue&#39;</span><span class="p">,</span> <span class="nx">autocompletedLabel</span><span class="p">);</span>
</span><span class='line'>            <span class="nx">Ember</span><span class="p">.</span><span class="nx">run</span><span class="p">.</span><span class="nx">next</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>              <span class="nx">resolve</span><span class="p">({</span> <span class="nx">start</span><span class="o">:</span> <span class="nx">value</span><span class="p">.</span><span class="nx">length</span><span class="p">,</span> <span class="nx">end</span><span class="o">:</span> <span class="nx">autocompletedLabel</span><span class="p">.</span><span class="nx">length</span> <span class="p">});</span>
</span><span class='line'>            <span class="p">});</span>
</span><span class='line'>          <span class="p">}</span>
</span><span class='line'>        <span class="p">});</span>
</span><span class='line'>      <span class="p">});</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<p>The code did not change a lot, but now a promise is returned on line 8. It is
resolved on 18, where <code>start</code> and <code>end</code> designate the cursor positions of the
selection.</p>

<p>The action handler in the <code>auto-complete-input</code> component needs to be modified
to set the selection higlight itself:</p>

<figure class='code'><figcaption><span></span></figcaption><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>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<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='js'><span class='line'><span class="c1">// addon/components/auto-complete-input.js</span>
</span><span class='line'><span class="kr">import</span> <span class="nx">Ember</span> <span class="nx">from</span> <span class="s1">&#39;ember&#39;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="kr">export</span> <span class="k">default</span> <span class="nx">Ember</span><span class="p">.</span><span class="nx">TextField</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span>
</span><span class='line'>  <span class="nx">valueDidChange</span><span class="o">:</span> <span class="nx">Ember</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">&#39;input&#39;</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="kr">const</span> <span class="nx">value</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">$</span><span class="p">().</span><span class="nx">val</span><span class="p">();</span>
</span><span class='line'>    <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;on-change&#39;</span><span class="p">)(</span><span class="nx">value</span><span class="p">).</span><span class="nx">then</span><span class="p">(({</span> <span class="nx">start</span><span class="p">,</span> <span class="nx">end</span> <span class="p">})</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span><span class='line'>      <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;element&#39;</span><span class="p">).</span><span class="nx">setSelectionRange</span><span class="p">(</span><span class="nx">start</span><span class="p">,</span> <span class="nx">end</span><span class="p">);</span>
</span><span class='line'>    <span class="p">});</span>
</span><span class='line'>  <span class="p">})</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<p>Calling <code>on-change</code> will call the above <code>inputDidChange</code> function. Instead of
firing the (element) action and forgetting about it, we now call the (closure)
action and then &#8220;wait&#8221; for the resulting promise to be resolved. Once it does,
we set the selection range.</p>

<p>We could now remove all the registration code and the passing down of the
autocomplete instance to the input component.</p>

<h2>Remove the need for direct access to the list options</h2>

<p>There is still another instance of the same. It serves to give access to the
<code>autocomplete</code> component to the <code>auto-complete-option</code>, through the
<code>auto-complete-list</code>.</p>

<div>
  <pre><code class='html'>&lt;!-- tests/dummy/app/templates/index.hbs --&gt;
{{#auto-complete
      on-select=(action &quot;selectArtist&quot;)
      on-input=(action &quot;filterArtists&quot;)
      class=&quot;autocomplete-container&quot; as |autocomplete isDropdownOpen inputValue
                                         toggleDropdown onSelect onInput|}}
  &lt;div class=&quot;input-group&quot;&gt;
    {{auto-complete-input
        value=inputValue
        on-change=onInput
        type=&quot;text&quot;
        class=&quot;combobox input-large form-control&quot;
        placeholder=&quot;Select an artist&quot;}}
    {{#auto-complete-list autocomplete=autocomplete isVisible=isDropdownOpen class=&quot;typeahead typeahead-long dropdown-menu&quot; as |list|}}
      {{#each matchingArtists as |artist|}}
        {{#auto-complete-option
            id=artist.id
            label=artist.name
            item=artist
            list=list
            on-click=onSelect
            activeId=selectedArtist.id}}
          &lt;a href=&quot;#&quot;&gt;{{artist.name}}&lt;/a&gt;
        {{/auto-complete-option}}
      {{/each}}
    {{/auto-complete-list}}
    (...)
  &lt;/div&gt;
{{/auto-complete}}</code></pre>
</div>


<p>I am not copying all the registration code here as it&#8217;s very boilerplatey. Each
option, when inserted into the DOM, registers itself with its list, while the
list registers itself with the <code>auto-complete</code> component. The latter has an
options property to access the options:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="c1">// addon/components/auto-complete.js</span>
</span><span class='line'><span class="nx">options</span><span class="o">:</span> <span class="nx">Ember</span><span class="p">.</span><span class="nx">computed</span><span class="p">.</span><span class="nx">readOnly</span><span class="p">(</span><span class="s1">&#39;list.options&#39;</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>This access is needed to be able to cycle through the options by using the
cursor keys and then select one of them by using the return key. Here is the
code that handles keypresses (more precisely, keydowns):</p>

<figure class='code'><figcaption><span></span></figcaption><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>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<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>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="c1">// addon/components/auto-complete.js</span>
</span><span class='line'><span class="kr">export</span> <span class="k">default</span> <span class="nx">Ember</span><span class="p">.</span><span class="nx">Component</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span>
</span><span class='line'>  <span class="p">(...)</span>
</span><span class='line'>  <span class="nx">keydownMap</span><span class="o">:</span> <span class="p">{</span>
</span><span class='line'>    <span class="mi">8</span><span class="o">:</span>  <span class="s1">&#39;startBackspacing&#39;</span><span class="p">,</span> <span class="c1">// backspace</span>
</span><span class='line'>    <span class="mi">13</span><span class="o">:</span> <span class="s1">&#39;selectOption&#39;</span><span class="p">,</span>  <span class="c1">// return</span>
</span><span class='line'>    <span class="mi">27</span><span class="o">:</span> <span class="s1">&#39;closeDropdown&#39;</span><span class="p">,</span> <span class="c1">// escape</span>
</span><span class='line'>    <span class="mi">38</span><span class="o">:</span> <span class="s1">&#39;focusPrevious&#39;</span><span class="p">,</span> <span class="c1">// up key</span>
</span><span class='line'>    <span class="mi">40</span><span class="o">:</span> <span class="s1">&#39;focusNext&#39;</span><span class="p">,</span> <span class="c1">// down key</span>
</span><span class='line'>  <span class="p">},</span>
</span><span class='line'>
</span><span class='line'>  <span class="nx">handleKeydown</span><span class="o">:</span> <span class="nx">Ember</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">&#39;keyDown&#39;</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="kr">const</span> <span class="nx">map</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;keydownMap&#39;</span><span class="p">);</span>
</span><span class='line'>    <span class="kr">const</span> <span class="nx">code</span> <span class="o">=</span> <span class="nx">event</span><span class="p">.</span><span class="nx">keyCode</span><span class="p">;</span>
</span><span class='line'>    <span class="kr">const</span> <span class="nx">method</span> <span class="o">=</span> <span class="nx">map</span><span class="p">[</span><span class="nx">code</span><span class="p">];</span>
</span><span class='line'>    <span class="k">if</span> <span class="p">(</span><span class="nx">method</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>      <span class="k">return</span> <span class="k">this</span><span class="p">[</span><span class="nx">method</span><span class="p">](</span><span class="nx">event</span><span class="p">);</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>  <span class="p">}),</span>
</span><span class='line'>  <span class="p">(...)</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<p>This is pretty simple so far. If a key we care about was pressed, we call the
appropriate method to handle it. Let&#8217;s see how focusing works:</p>

<figure class='code'><figcaption><span></span></figcaption><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>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<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>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="c1">// addon/components/auto-complete.js</span>
</span><span class='line'><span class="kr">export</span> <span class="k">default</span> <span class="nx">Ember</span><span class="p">.</span><span class="nx">Component</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span>
</span><span class='line'>  <span class="p">(...)</span>
</span><span class='line'>  <span class="nx">options</span><span class="o">:</span> <span class="nx">Ember</span><span class="p">.</span><span class="nx">computed</span><span class="p">.</span><span class="nx">readOnly</span><span class="p">(</span><span class="s1">&#39;list.options&#39;</span><span class="p">),</span>
</span><span class='line'>
</span><span class='line'>  <span class="nx">focusPrevious</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="nx">event</span><span class="p">.</span><span class="nx">preventDefault</span><span class="p">();</span>
</span><span class='line'>    <span class="kr">const</span> <span class="nx">focused</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;focusedOption&#39;</span><span class="p">);</span>
</span><span class='line'>    <span class="kd">let</span> <span class="nx">index</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;options&#39;</span><span class="p">).</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">focused</span><span class="p">);</span>
</span><span class='line'>    <span class="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;isDropdownOpen&#39;</span><span class="p">))</span> <span class="p">{</span>
</span><span class='line'>      <span class="nx">index</span> <span class="o">=</span> <span class="nx">index</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>    <span class="k">this</span><span class="p">.</span><span class="nx">focusOptionAtIndex</span><span class="p">(</span><span class="nx">index</span><span class="p">);</span>
</span><span class='line'>  <span class="p">},</span>
</span><span class='line'>
</span><span class='line'>  <span class="nx">focusNext</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="nx">event</span><span class="p">.</span><span class="nx">preventDefault</span><span class="p">();</span>
</span><span class='line'>    <span class="kd">let</span> <span class="nx">index</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span><span class='line'>    <span class="kr">const</span> <span class="nx">focused</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;focusedOption&#39;</span><span class="p">);</span>
</span><span class='line'>    <span class="k">if</span> <span class="p">(</span><span class="nx">focused</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>      <span class="nx">index</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;options&#39;</span><span class="p">).</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">focused</span><span class="p">);</span>
</span><span class='line'>      <span class="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;isDropdownOpen&#39;</span><span class="p">))</span> <span class="p">{</span>
</span><span class='line'>        <span class="nx">index</span> <span class="o">=</span> <span class="nx">index</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
</span><span class='line'>      <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>    <span class="k">this</span><span class="p">.</span><span class="nx">focusOptionAtIndex</span><span class="p">(</span><span class="nx">index</span><span class="p">);</span>
</span><span class='line'>  <span class="p">},</span>
</span><span class='line'>
</span><span class='line'>  <span class="nx">focusOptionAtIndex</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">index</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="kr">const</span> <span class="nx">options</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;options&#39;</span><span class="p">);</span>
</span><span class='line'>    <span class="k">if</span> <span class="p">(</span><span class="nx">index</span> <span class="o">===</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>      <span class="nx">index</span> <span class="o">=</span> <span class="nx">options</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;length&#39;</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">index</span> <span class="o">===</span> <span class="nx">options</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;length&#39;</span><span class="p">))</span> <span class="p">{</span>
</span><span class='line'>      <span class="nx">index</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>    <span class="kr">const</span> <span class="nx">option</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;options&#39;</span><span class="p">).</span><span class="nx">objectAt</span><span class="p">(</span><span class="nx">index</span><span class="p">);</span>
</span><span class='line'>    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">option</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>      <span class="k">return</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>    <span class="k">this</span><span class="p">.</span><span class="nx">focusOption</span><span class="p">(</span><span class="nx">option</span><span class="p">);</span>
</span><span class='line'>  <span class="p">},</span>
</span><span class='line'>
</span><span class='line'>  <span class="nx">focusOption</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">option</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="kr">const</span> <span class="nx">focused</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;focusedOption&#39;</span><span class="p">);</span>
</span><span class='line'>    <span class="k">if</span> <span class="p">(</span><span class="nx">focused</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>      <span class="nx">focused</span><span class="p">.</span><span class="nx">blur</span><span class="p">();</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>    <span class="k">this</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="s1">&#39;focusedOption&#39;</span><span class="p">,</span> <span class="nx">option</span><span class="p">);</span>
</span><span class='line'>    <span class="nx">option</span><span class="p">.</span><span class="nx">focus</span><span class="p">();</span>
</span><span class='line'>  <span class="p">},</span>
</span><span class='line'>  <span class="p">(...)</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<p><code>focusPrevious</code> and <code>focusNext</code> make sure that the focused index is kept within
the bounds of the avaiable number of options and then focus the previous (or
next) one by calling <code>option.focus()</code> directly (line 49).</p>

<p>There is one more key press concerning related to options, the return key. It
should select the currently focused option, if there is one:</p>

<figure class='code'><figcaption><span></span></figcaption><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>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<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>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="c1">// addon/components/auto-complete.js</span>
</span><span class='line'><span class="kr">export</span> <span class="k">default</span> <span class="nx">Ember</span><span class="p">.</span><span class="nx">Component</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span>
</span><span class='line'>  <span class="p">(...)</span>
</span><span class='line'>  <span class="nx">options</span><span class="o">:</span> <span class="nx">Ember</span><span class="p">.</span><span class="nx">computed</span><span class="p">.</span><span class="nx">readOnly</span><span class="p">(</span><span class="s1">&#39;list.options&#39;</span><span class="p">),</span>
</span><span class='line'>  <span class="nx">selectOption</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="nx">event</span><span class="p">.</span><span class="nx">preventDefault</span><span class="p">();</span>
</span><span class='line'>    <span class="kr">const</span> <span class="nx">focused</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;focusedOption&#39;</span><span class="p">);</span>
</span><span class='line'>    <span class="k">if</span> <span class="p">(</span><span class="nx">focused</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>      <span class="k">this</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="s1">&#39;selectItem&#39;</span><span class="p">,</span> <span class="nx">focused</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;item&#39;</span><span class="p">),</span> <span class="nx">focused</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;label&#39;</span><span class="p">));</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>    <span class="k">this</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="s1">&#39;isDropdownOpen&#39;</span><span class="p">,</span> <span class="kc">false</span><span class="p">);</span>
</span><span class='line'>  <span class="p">},</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<p>This code also leverages the access to the options, indirectly through
<code>this.get('focusedOption')</code>. Furthermore, it assumes that each option has an
<code>item</code> and <code>label</code> properties. Not stellar.</p>

<p>It won&#8217;t be a piece of cake to get rid of direct coupling in all of these, so
let&#8217;s get to it.</p>

<h3>Change the focused option without accessing the options</h3>

<p>In the first step, we&#8217;ll change the focused option without directly commanding
the options to focus/unfocus. We&#8217;ll then tackle selecting the focused option.</p>

<p>We can use simple data binding to have the focused option available. By
maintaining and yielding a <code>focusedIndex</code> in the &#8220;control center&#8221;, the
<code>autocomplete</code> component, <code>autocomplete-option</code> components can bind to it and
know whether they are focused or not.</p>

<p>Here is how the templates need to change:</p>

<div>
  <pre><code class='html'>&lt;!-- addon/templates/components/autocomplete.hbs --&gt;
{{yield isDropdownOpen
        inputValue
        focusedIndex
        selectedIndex
        (action &quot;toggleDropdown&quot;)
        (action &quot;selectItem&quot;)
        (action &quot;inputDidChange&quot;)}}</code></pre>
</div>




<div>
  <pre><code class='html'>&lt;!-- tests/dummy/app/templates/index.hbs --&gt;
{{#auto-complete
      on-select=(action &quot;selectArtist&quot;)
      on-input=(action &quot;filterArtists&quot;)
      options=matchingArtists
      displayProperty=&quot;name&quot;
      class=&quot;autocomplete-container&quot; as |isDropdownOpen inputValue
                                         focusedIndex selectedIndex
                                         toggleDropdown onSelect onInput|}}
  &lt;div class=&quot;input-group&quot;&gt;
    {{auto-complete-input
        value=inputValue
        on-change=onInput
        type=&quot;text&quot;
        class=&quot;combobox input-large form-control&quot;
        placeholder=&quot;Select an artist&quot;}}
    {{#auto-complete-list
        isVisible=isDropdownOpen
        class=&quot;typeahead typeahead-long dropdown-menu&quot; as |list|}}
      {{#each matchingArtists as |artist index|}}
        {{#auto-complete-option
            label=artist.name
            item=artist
            on-click=onSelect
            isFocused=(eq focusedIndex index)
            isSelected=(eq selectedIndex index)}}
          &lt;a href=&quot;#&quot;&gt;{{artist.name}}&lt;/a&gt;
        {{/auto-complete-option}}
      {{else}}
        &lt;li&gt;&lt;a href=&quot;#&quot;&gt;No results.&lt;/a&gt;&lt;/li&gt;
      {{/each}}
    {{/auto-complete-list}}
    (...)
  &lt;/div&gt;
{{/auto-complete}}</code></pre>
</div>


<p>Note the new <code>focusedIndex</code> and <code>selectedIndex</code> attributes, yielded by the
top-level component that <code>isFocused</code> and <code>isSelected</code> in the
<code>auto-complete-option</code> are bound to.</p>

<p>The <code>eq</code> helper comes from <a href="https://github.com/jmurphyau/ember-truth-helpers">ember-truth-helpers</a> and will evaluate to true if
its params are equal which is exactly what we want.</p>

<p>The <code>autocomplete</code> component needs to change to manage the new indexes instead
of setting its <code>focusedOption</code> and calling <code>option.set</code> directly:</p>

<figure class='code'><figcaption><span></span></figcaption><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>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<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>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="c1">// addon/components/auto-complete.js</span>
</span><span class='line'><span class="kr">export</span> <span class="k">default</span> <span class="nx">Ember</span><span class="p">.</span><span class="nx">Component</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span>
</span><span class='line'>  <span class="p">(...)</span>
</span><span class='line'>  <span class="nx">optionsLength</span><span class="o">:</span> <span class="nx">Ember</span><span class="p">.</span><span class="nx">computed</span><span class="p">.</span><span class="nx">readOnly</span><span class="p">(</span><span class="s1">&#39;options.length&#39;</span><span class="p">),</span>
</span><span class='line'>  <span class="nx">focusPrevious</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="nx">event</span><span class="p">.</span><span class="nx">preventDefault</span><span class="p">();</span>
</span><span class='line'>    <span class="kr">const</span> <span class="nx">currentIndex</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;focusedIndex&#39;</span><span class="p">);</span>
</span><span class='line'>    <span class="kd">let</span> <span class="nx">newIndex</span><span class="p">;</span>
</span><span class='line'>    <span class="k">if</span> <span class="p">(</span><span class="nx">Ember</span><span class="p">.</span><span class="nx">isNone</span><span class="p">(</span><span class="nx">currentIndex</span><span class="p">))</span> <span class="p">{</span>
</span><span class='line'>      <span class="nx">newIndex</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;optionsLength&#39;</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">currentIndex</span> <span class="o">===</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>      <span class="nx">newIndex</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;optionsLength&#39;</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span><span class='line'>      <span class="nx">newIndex</span> <span class="o">=</span> <span class="nx">currentIndex</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>    <span class="k">this</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="s1">&#39;focusedIndex&#39;</span><span class="p">,</span> <span class="nx">newIndex</span><span class="p">);</span>
</span><span class='line'>    <span class="k">this</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="s1">&#39;isDropdownOpen&#39;</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span>
</span><span class='line'>  <span class="p">},</span>
</span><span class='line'>
</span><span class='line'>  <span class="nx">focusNext</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="nx">event</span><span class="p">.</span><span class="nx">preventDefault</span><span class="p">();</span>
</span><span class='line'>    <span class="kr">const</span> <span class="nx">currentIndex</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;focusedIndex&#39;</span><span class="p">);</span>
</span><span class='line'>    <span class="kr">const</span> <span class="nx">lastIndex</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;optionsLength&#39;</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span>
</span><span class='line'>    <span class="kd">let</span> <span class="nx">newIndex</span><span class="p">;</span>
</span><span class='line'>    <span class="k">if</span> <span class="p">(</span><span class="nx">Ember</span><span class="p">.</span><span class="nx">isNone</span><span class="p">(</span><span class="nx">currentIndex</span><span class="p">))</span> <span class="p">{</span>
</span><span class='line'>      <span class="nx">newIndex</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">currentIndex</span> <span class="o">===</span> <span class="nx">lastIndex</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>      <span class="nx">newIndex</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span><span class='line'>      <span class="nx">newIndex</span> <span class="o">=</span> <span class="nx">currentIndex</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>    <span class="k">this</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="s1">&#39;focusedIndex&#39;</span><span class="p">,</span> <span class="nx">newIndex</span><span class="p">);</span>
</span><span class='line'>    <span class="k">this</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="s1">&#39;isDropdownOpen&#39;</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span>
</span><span class='line'>  <span class="p">},</span>
</span><span class='line'>
</span><span class='line'>  <span class="nx">selectOption</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="nx">event</span><span class="p">.</span><span class="nx">preventDefault</span><span class="p">();</span>
</span><span class='line'>    <span class="kr">const</span> <span class="nx">focusedIndex</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;focusedIndex&#39;</span><span class="p">);</span>
</span><span class='line'>    <span class="k">if</span> <span class="p">(</span><span class="nx">Ember</span><span class="p">.</span><span class="nx">isPresent</span><span class="p">(</span><span class="nx">focusedIndex</span><span class="p">))</span> <span class="p">{</span>
</span><span class='line'>      <span class="k">this</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="s1">&#39;selectedIndex&#39;</span><span class="p">,</span> <span class="nx">focusedIndex</span><span class="p">);</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>    <span class="k">this</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="s1">&#39;isDropdownOpen&#39;</span><span class="p">,</span> <span class="kc">false</span><span class="p">);</span>
</span><span class='line'>  <span class="p">},</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<p>That is simpler and less intrusive than before. (Setting <code>isDropdown</code> to true
has been added as before the option&#8217;s <code>focus</code> method did the opening).</p>

<p>What&#8217;s missing is for the selected item to be sent to the outer world (in other
words, for the <code>selectItem</code> to be triggered). Before, it was done by sending
the <code>selectItem</code> action with the focused option&#8217;s item and label (see line 9 in
the last snippet of the previous section) but we can no longer indulge in
accessing the options directly. Consequently, it was replaced by setting the
<code>selectedIndex</code> to the <code>focusedIndex</code> (see line 40 above).</p>

<p>The problem now is that <code>selectItem</code> needs to be called with the item and the
label (the name of the selected artist to be set as the input&#8217;s value) and only
the selected <code>auto-complete-option</code> component has that knowledge. So we need to
set up a way for the <code>auto-complete-option</code> components to know when they become
selected and then call that action. As these components are not the source of
the event that lead to an option being selected by key press, we choose to use
an observer:</p>

<figure class='code'><figcaption><span></span></figcaption><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>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<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>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="c1">// addon/components/auto-complete-option.js</span>
</span><span class='line'><span class="kr">import</span> <span class="nx">Ember</span> <span class="nx">from</span> <span class="s1">&#39;ember&#39;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="kr">export</span> <span class="k">default</span> <span class="nx">Ember</span><span class="p">.</span><span class="nx">Component</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span>
</span><span class='line'>  <span class="nx">tagName</span><span class="o">:</span> <span class="s1">&#39;li&#39;</span><span class="p">,</span>
</span><span class='line'>  <span class="nx">classNames</span><span class="o">:</span> <span class="s1">&#39;ember-autocomplete-option&#39;</span><span class="p">,</span>
</span><span class='line'>  <span class="nx">classNameBindings</span><span class="o">:</span> <span class="nx">Ember</span><span class="p">.</span><span class="nb">String</span><span class="p">.</span><span class="nx">w</span><span class="p">(</span><span class="s1">&#39;isSelected:active isFocused:focused&#39;</span><span class="p">),</span>
</span><span class='line'>
</span><span class='line'>  <span class="nx">label</span><span class="o">:</span> <span class="kc">null</span><span class="p">,</span>
</span><span class='line'>  <span class="nx">item</span><span class="o">:</span> <span class="kc">null</span><span class="p">,</span>
</span><span class='line'>  <span class="s1">&#39;on-click&#39;</span><span class="o">:</span> <span class="kc">null</span><span class="p">,</span>
</span><span class='line'>  <span class="nx">isFocused</span><span class="o">:</span> <span class="kc">false</span><span class="p">,</span>
</span><span class='line'>  <span class="nx">isSelected</span><span class="o">:</span> <span class="kc">false</span><span class="p">,</span>
</span><span class='line'>
</span><span class='line'>  <span class="nx">didClick</span><span class="o">:</span> <span class="nx">Ember</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">&#39;click&#39;</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">this</span><span class="p">.</span><span class="nx">_selectItem</span><span class="p">();</span>
</span><span class='line'>  <span class="p">}),</span>
</span><span class='line'>
</span><span class='line'>  <span class="nx">didBecomeSelected</span><span class="o">:</span> <span class="nx">Ember</span><span class="p">.</span><span class="nx">observer</span><span class="p">(</span><span class="s1">&#39;isSelected&#39;</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="kr">const</span> <span class="nx">isSelected</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;isSelected&#39;</span><span class="p">);</span>
</span><span class='line'>    <span class="k">if</span> <span class="p">(</span><span class="nx">isSelected</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>      <span class="k">this</span><span class="p">.</span><span class="nx">_selectItem</span><span class="p">();</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>  <span class="p">}),</span>
</span><span class='line'>
</span><span class='line'>  <span class="nx">_selectItem</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="kr">const</span> <span class="nx">item</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;item&#39;</span><span class="p">);</span>
</span><span class='line'>    <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;on-click&#39;</span><span class="p">)(</span><span class="nx">item</span><span class="p">,</span> <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;label&#39;</span><span class="p">));</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<p>Line 21 and 22 is where the option realizes it has become the selected option,
and then calls the corresponding (closure) action on line 28.</p>

<p>We&#8217;re done, we got rid of all the direct passing of component instances,
registrations and direct property access and method calling. Even though we&#8217;re
<a href="http://www.ccs.neu.edu/research/demeter/demeter-method/LawOfDemeter/paper-boy/demeter.pdf">Demeter compliant</a>, there are things that could be improved.</p>

<h3>In the next episode&#8230;</h3>

<p>One of these things is the observer. <a href="https://www.youtube.com/watch?v=7PUX27RKCq0">Observers fell out of favor</a> some time
ago, and for a good reason. They can be over-eager and lead to scenarios where
it is hard to see what&#8217;s going on. To prove my point, let me show you a bug I&#8217;ve
just accidentally introduced. I call it the &#8220;JPJ is too good to be replaced&#8221; bug:</p>

<p><img src="http://balinterdi.com/images/posts/complex-component-design-ember/jpj-too-good-bug.gif" alt="JPJ is too good to be replaced" /></p>

<p>(The code for this series is publicly available on Github <a href="https://github.com/balinterdi/ember-cli-autocomplete">here</a>. I&#8217;ve tagged
where we are now with <a href="https://github.com/balinterdi/ember-cli-autocomplete/releases/tag/ccd-part-two">ccd-part-two</a>.)</p>

<p>So we&#8217;re not done yet. In the next post of the series, we&#8217;re going to fix that
bug by replacing the observer and make other worthy improvements. Stay tuned!</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Binding style attributes warning in Ember]]></title>
    <link href="http://balinterdi.com/2016/02/03/binding-style-attributes-warning-in-ember.html"/>
    <updated>2016-02-03T09:33:00+01:00</updated>
    <id>http://balinterdi.com/2016/02/03/binding-style-attributes-warning-in-ember</id>
    <content type="html"><![CDATA[<p>One warning Ember might print in your console concerns binding a property to
the <code>style</code> attribute of a DOM element, like this:</p>

<div>
  <pre><code class='html'>&lt;div class=&quot;progress-bar&quot; style=&quot;{{barWidth}}&quot;&gt;...&lt;/div&gt;</code></pre>
</div>




<div>
  <pre><code class='javascript'>export default Ember.Controller.extend({
  progress: 0,
  barWidth: Ember.computed(&#39;progress&#39;, {
    return &#39;width:&#39; + this.get(&#39;progress&#39;) + &#39;%&#39;;
  });
});</code></pre>
</div>


<p>Handlebars escapes all html content put in double curlies but it does not do
that with CSS, and thus the above makes possible a cross-site scripting attack.
That is the reason for the warning and the fix for that is to convert the
property (in the above case, <code>barWidth</code>) to a <code>SafeString</code>, which tells Ember
that the content is safe to display. You should only do that after you have
verified that the content you mark as safe cannot be injected by a malicious
user. <a href="http://emberjs.com/deprecations/v1.x/#toc_binding-style-attributes">The guide</a> describes how to do that:</p>

<div>
  <pre><code class='javascript'>export default Ember.Controller.extend({
  progress: 0,
  barWidth: Ember.computed(&#39;progress&#39;, {
    return new Ember.Handlebars.SafeString(&#39;width:&#39; + this.get(&#39;progress&#39;) + &#39;%&#39;);
  });
});</code></pre>
</div>


<p>(Alternatively, you can call <code>Ember.String.htmlSafe</code> with the string you want to
mark as safe, to the same effect.)</p>

<p>When I did this conversion in a recent project, though, the warning persisted.
After spending a substantial amount of time pouring over the docs and even
stepping through the warning stacktrace, I still could not find out what was
wrong. What helped (as so many times already) was a good night sleep and taking
another look at it in the morning.</p>

<p>Marking the string as safe was done correctly, but when binding it to the
<code>style</code> attribute, I used double quotes around it, probably inhibiting Ember
from seeing it as a SafeString:</p>

<div>
  <pre><code class='html'>&lt;div class=&quot;progress-bar&quot; style=&quot;{{barWidth}}&quot;&gt;...&lt;/div&gt;</code></pre>
</div>


<p>So all I had to do to make the warning go away was to remove the quotes:</p>

<div>
  <pre><code class='html'>&lt;div class=&quot;progress-bar&quot; style={{barWidth}}&gt;...&lt;/div&gt;</code></pre>
</div>


<p>I hope this saves you some time if you come across a similar situation in your
work.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Rock and Roll with Ember.js updated to use Ember &amp; Co 2.3]]></title>
    <link href="http://balinterdi.com/2016/01/21/rock-and-roll-with-ember-dot-js-updated-to-use-ember-and-co-2-dot-3.html"/>
    <updated>2016-01-21T14:50:00+01:00</updated>
    <id>http://balinterdi.com/2016/01/21/rock-and-roll-with-ember-dot-js-updated-to-use-ember-and-co-2-dot-3</id>
    <content type="html"><![CDATA[<p>I have just released a new update to <a href="http://rockandrollwithemberjs.com">the Rock and Roll Ember.js book</a>,
which brings it up to Ember 2.3.0, ED 2.3.2 and Ember CLI 2.3.0-beta.1.</p>

<p>Other improvements made in this release are:</p>

<ul>
<li>Update the PageFront section as it has now become even simpler to deploy apps to PageFront</li>
<li>Reset the song creation process when switching bands</li>
<li>Use ember-bootstrap and remove the section on manually adding assets to the build</li>
<li>Use consistent quoting in snippets and include <code>import Ember from 'ember'</code> wherever needed.</li>
<li>Remove a few paragraphs that talk about how things were in the past (like <code>bind-attr</code>)</li>
</ul>


<p>Happy reading!</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Complex Components in Ember.js - Part 1 - Analyzing user flows]]></title>
    <link href="http://balinterdi.com/2015/12/18/complex-components-in-ember-dot-js-part-1-analyzing-user-flows.html"/>
    <updated>2015-12-18T10:25:00+01:00</updated>
    <id>http://balinterdi.com/2015/12/18/complex-components-in-ember-dot-js-part-1-analyzing-user-flows</id>
    <content type="html"><![CDATA[<p><em>This is Part 1 of the Complex Component Design series. Here are the posts in the series:</em></p>

<ul>
<li><a href="http://balinterdi.com/2015/09/10/complex-component-design-in-ember-intro.html"><strong>Intro</strong></a></li>
<li><strong>Part 1 - Analyzing User Flows</strong></li>
<li><a href="http://balinterdi.com/2016/02/04/complex-components-in-ember-dot-js-part-2-towards-a-more-reactive-component.html"><strong>Part 2 - Towards a more reactive component</strong></a></li>
<li><a href="http://balinterdi.com/2016/04/08/complex-component-design-in-ember-replace-the-observer.html"><strong>Part 3 - Remove the observer</strong></a></li>
<li><a href="http://balinterdi.com/2016/05/26/complex-component-design-in-ember-part-4-use-the-hash-helper.html"><strong>Part 4 - Use the hash helper</strong></a></li>
</ul>


<hr />

<p>In this post I continue the <a href="http://balinterdi.com/2015/09/10/complex-component-design-in-ember-intro.html">Complex Component Design series</a> I started back in
September. I slightly renamed the series title as the original idea was to
design and develop the component in the parts of the series but since the
component is mostly &#8220;done&#8221;, I prefer to show how it works and how the different
pieces fit together. I think this way of presenting things is still (perhaps
equally) valuable and we&#8217;ll have a few open issues to work on &#8220;together&#8221; to
further improve the component.</p>

<p>The component I described in <a href="http://balinterdi.com/2015/09/10/complex-component-design-in-ember-intro.html">the intro post</a> serves to select an item from a
list of items, either via a dropdown or by starting to type its name and then
selecting it. Here is a very short demo about how that looks in practice:</p>

<p><img src="http://balinterdi.com/images/posts/complex-component-design-ember/ember-autocomplete-demo.gif" alt="Selecting an artist" /></p>

<p>We&#8217;ll go through the main UI flows and see how they are implemented via
communication of the different layers of the component.</p>

<h2>Getting familiar with the component</h2>

<p>The template we&#8217;ll use (and which the above demo uses) to understand the
functioning of the component looks like this:</p>

<div>
  <pre><code class='html'>&lt;!-- tests/dummy/app/templates/index.hbs --&gt;
&lt;div class=&quot;form-group&quot;&gt;
  &lt;label&gt;Choose an artist&lt;/label&gt;
  {{#auto-complete
        on-select=(action &quot;selectArtist&quot;)
        on-input=(action &quot;filterArtists&quot;)
        class=&quot;autocomplete-container&quot; as |autocomplete isDropdownOpen inputValue
                                           toggleDropdown onSelect onInput|}}
    &lt;div class=&quot;input-group&quot;&gt;
      {{auto-complete-input
          autocomplete=autocomplete
          value=inputValue
          on-change=onInput
          type=&quot;text&quot;
          class=&quot;combobox input-large form-control&quot;
          placeholder=&quot;Select an artist&quot;}}
      {{#auto-complete-list autocomplete=autocomplete isVisible=isDropdownOpen
              class=&quot;typeahead typeahead-long dropdown-menu&quot; as |list|}}
        {{#each matchingArtists as |artist|}}
          {{#auto-complete-option
              id=artist.id
              label=artist.name
              item=artist
              list=list
              on-click=onSelect
              activeId=selectedArtist.id}}
            &lt;a href=&quot;#&quot;&gt;{{artist.name}}&lt;/a&gt;
          {{/auto-complete-option}}
        {{else}}
          &lt;li&gt;&lt;a href=&quot;#&quot;&gt;No results.&lt;/a&gt;&lt;/li&gt;
        {{/each}}
      {{/auto-complete-list}}
      {{#auto-complete-dropdown-toggle on-click=toggleDropdown
              class=&quot;input-group-addon dropdown-toggle&quot;}}
        &lt;span class=&quot;caret&quot;&gt;&lt;/span&gt;
      {{/auto-complete-dropdown-toggle}}
    &lt;/div&gt;
  {{/auto-complete}}
&lt;/div&gt;</code></pre>
</div>


<p>This might seem somewhat daunting at first but as we grow acquainted with its
details, our intimidation will subside.</p>

<p>The top-level component is <code>auto-complete</code>. This is the &#8220;command center&#8221;, the
piece that manages the &#8220;global&#8221; state of the whole widget, like whether the
dropdown is visible and what the current value of the input field is.</p>

<p>You might, with good reason, wonder why these are not handled by the
sub-component where it&#8217;d feel more appropriate: the current value of the input
field by <code>auto-complete-input</code> and the opened/closed state of the dropdown by
<code>auto-complete-dropdown-toggle</code>.</p>

<p>The answer is that a change in these states can be triggered from multiple
places and that several child components might need to know about them. The
dropdown can be closed by the user clicking on one of the items in the dropdown
(not on the little arrow of the toggle), while the current text in the input can
be modified by inferring the item when the user starts to type (not just by
actually typing out the whole text).</p>

<h3>Data down, actions up - all the way down (and up)</h3>

<p>That slight violation of separation of concerns (or is it at all?) fits
perfectly with the most important component communication paradigm: Data down,
actions up.</p>

<p>The input, when its value changes, sends an action up to its parent, notifying
it of the change. The parent can then react to this, and communicate any data
(state) changes via the attribute bindings it has to the input. This is why
<code>auto-complete</code> needs to handle, or at least access, state that is used
downstream by its sub-components.</p>

<p>The classical way of passing down data (and establishing a binding) from the
parent to the child is through block parameters of the parent component. The
<code>auto-complete</code> component has quite some:</p>

<div>
  <pre><code class='html'>&lt;!-- tests/dummy/app/templates/index.hbs --&gt;
{{#auto-complete
      on-select=(action &quot;selectArtist&quot;)
      on-input=(action &quot;filterArtists&quot;)
      class=&quot;autocomplete-container&quot; as |autocomplete isDropdownOpen inputValue
                                         toggleDropdown onSelect onInput|}}
  (...)
{{/auto-complete}}</code></pre>
</div>


<p>The block parameters are those found between the pipes, after the <code>as</code> keyword.
You have to look into the component&#8217;s own template to see where they come from:</p>

<div>
  <pre><code class='html'>&lt;!-- addon/templates/components/auto-complete.hbs --&gt;
{{yield this isDropdownOpen inputValue
        (action &quot;toggleDropdown&quot;) (action &quot;selectItem&quot;) (action &quot;inputDidChange&quot;)}}</code></pre>
</div>


<p>Parameters are matched by position, so what is yielded in the first position
becomes the first block parameter. In this case, we yield the component itself
as the first parameter, the aforementioned component states as the 2nd and 3rd
and then (closure) actions that will trigger functions in the <code>auto-complete</code>
component when called in one of the child components. These serve as &#8220;remote
controls&#8221; (a term used by <a href="https://twitter.com/miguelcamba">Miguel Camba</a> in his <a href="https://www.youtube.com/watch?v=6N4qsO22fmw">awesome presentation at
EmberCamp</a>) for child components to control their parent.</p>

<p>The way of upward communication from child components is calling these actions
when appropriate.</p>

<p>We now have sufficient knowledge to follow the implemention of basic user flows,
so let&#8217;s get into it.</p>

<h2>Understanding UX flows</h2>

<h3>Manual selection from the dropdown</h3>

<p>The most basic thing one can do with the widget is to pop open the list of
options.</p>

<p>I discarded the parts that are not relevant to understand this, so we&#8217;re left
with the following:</p>

<div>
  <pre><code class='html'>&lt;!-- tests/dummy/app/templates/index.hbs --&gt;
&lt;div class=&quot;form-group&quot;&gt;
  &lt;label&gt;Choose an artist&lt;/label&gt;
  {{#auto-complete
        on-select=(action &quot;selectArtist&quot;)
        on-input=(action &quot;filterArtists&quot;)
        class=&quot;autocomplete-container&quot; as |autocomplete isDropdownOpen inputValue
                                           toggleDropdown onSelect onInput|}}
    &lt;div class=&quot;input-group&quot;&gt;
      {{#auto-complete-list autocomplete=autocomplete isVisible=isDropdownOpen
              class=&quot;typeahead typeahead-long dropdown-menu&quot; as |list|}}
        (...)
      {{/auto-complete-list}}
      {{#auto-complete-dropdown-toggle on-click=toggleDropdown
              class=&quot;input-group-addon dropdown-toggle&quot;}}
        &lt;span class=&quot;caret&quot;&gt;&lt;/span&gt;
      {{/auto-complete-dropdown-toggle}}
    &lt;/div&gt;
  {{/auto-complete}}
&lt;/div&gt;</code></pre>
</div>


<p>The <code>auto-complete-dropdown-toggle</code> is the component that can be clicked to open
or close the list of items. At a glance it seems like its <code>on-click</code> attribute
is the action that will be triggered when the user clicks it but let&#8217;s see for
sure:</p>

<figure class='code'><figcaption><span></span></figcaption><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>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<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>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="c1">// addon/components/auto-complete-dropdown-toggle.js</span>
</span><span class='line'><span class="kr">import</span> <span class="nx">Ember</span> <span class="nx">from</span> <span class="s1">&#39;ember&#39;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="kr">export</span> <span class="k">default</span> <span class="nx">Ember</span><span class="p">.</span><span class="nx">Component</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span>
</span><span class='line'>  <span class="nx">tagName</span><span class="o">:</span> <span class="s1">&#39;span&#39;</span><span class="p">,</span>
</span><span class='line'>  <span class="nx">classNames</span><span class="o">:</span> <span class="s1">&#39;ember-autocomplete-toggle&#39;</span><span class="p">,</span>
</span><span class='line'>  <span class="s1">&#39;data-dropdown&#39;</span><span class="o">:</span> <span class="s1">&#39;dropdown&#39;</span><span class="p">,</span>
</span><span class='line'>  <span class="s1">&#39;on-click&#39;</span><span class="o">:</span> <span class="kc">null</span><span class="p">,</span>
</span><span class='line'>
</span><span class='line'>  <span class="nx">toggleDropdown</span><span class="o">:</span> <span class="nx">Ember</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">&#39;click&#39;</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;on-click&#39;</span><span class="p">)();</span>
</span><span class='line'>  <span class="p">})</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<p>Indeed, it just calls the action that was passed into it, which is
the <code>toggleDropdown</code> action of the topmost <code>auto-complete</code> component:</p>

<figure class='code'><figcaption><span></span></figcaption><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>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<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='js'><span class='line'><span class="c1">// addon/components/auto-complete.js</span>
</span><span class='line'><span class="kr">import</span> <span class="nx">Ember</span> <span class="nx">from</span> <span class="s1">&#39;ember&#39;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="kr">export</span> <span class="k">default</span> <span class="nx">Ember</span><span class="p">.</span><span class="nx">Component</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span>
</span><span class='line'>  <span class="p">(...)</span>
</span><span class='line'>  <span class="nx">actions</span><span class="o">:</span> <span class="p">{</span>
</span><span class='line'>    <span class="nx">toggleDropdown</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>      <span class="k">this</span><span class="p">.</span><span class="nx">toggleProperty</span><span class="p">(</span><span class="s1">&#39;isDropdownOpen&#39;</span><span class="p">);</span>
</span><span class='line'>    <span class="p">},</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<p>The <code>toggleProperty</code> method flips the value of its parameter, so if it was false
it now becomes true. <code>isDropdownOpen</code> is yielded as a block parameter so when it
becomes true, <code>auto-complete-list</code> will rerender as one of its attributes,
<code>isVisible</code> has changed. That will then open the dropdown:</p>

<div>
  <pre><code class='html'>&lt;!-- tests/dummy/app/templates/index.hbs --&gt;
&lt;div class=&quot;form-group&quot;&gt;
  &lt;label&gt;Choose an artist&lt;/label&gt;
  {{#auto-complete
      (...)
      class=&quot;autocomplete-container&quot; as |autocomplete isDropdownOpen inputValue
                                           toggleDropdown onSelect onInput|}}
    &lt;div class=&quot;input-group&quot;&gt;
      {{#auto-complete-list autocomplete=autocomplete isVisible=isDropdownOpen
              class=&quot;typeahead typeahead-long dropdown-menu&quot; as |list|}}
        (...)
      {{/auto-complete-list}}
    &lt;/div&gt;
  {{/auto-complete}}
&lt;/div&gt;</code></pre>
</div>


<p>The same process is triggered when the toggle is clicked again, only this time
<code>isDropdownOpen</code> goes back to false and thus the dropdown is closed.</p>

<h3>Picking an item</h3>

<p>The second feature we&#8217;ll look at is more like the second half of the first one:
selecting an item by clicking (tapping) on it.</p>

<p>I have again restrained the template to the relevant bits, throwing away the
input and the toggle:</p>

<div>
  <pre><code class='html'>&lt;!-- tests/dummy/app/templates/index.hbs --&gt;
&lt;div class=&quot;form-group&quot;&gt;
  &lt;label&gt;Choose an artist&lt;/label&gt;
  {{#auto-complete
        on-select=(action &quot;selectArtist&quot;)
        on-input=(action &quot;filterArtists&quot;)
        class=&quot;autocomplete-container&quot; as |autocomplete isDropdownOpen inputValue
                                           toggleDropdown onSelect onInput|}}
    &lt;div class=&quot;input-group&quot;&gt;
      (...)
      {{#auto-complete-list autocomplete=autocomplete isVisible=isDropdownOpen
              class=&quot;typeahead typeahead-long dropdown-menu&quot; as |list|}}
        {{#each matchingArtists as |artist|}}
          {{#auto-complete-option
              id=artist.id
              label=artist.name
              item=artist
              list=list
              on-click=onSelect
              activeId=selectedArtist.id}}
            &lt;a href=&quot;#&quot;&gt;{{artist.name}}&lt;/a&gt;
          {{/auto-complete-option}}
        {{else}}
          &lt;li&gt;&lt;a href=&quot;#&quot;&gt;No results.&lt;/a&gt;&lt;/li&gt;
        {{/each}}
      {{/auto-complete-list}}
      (...)
    &lt;/div&gt;
  {{/auto-complete}}
&lt;/div&gt;</code></pre>
</div>


<p>When one of the items is clicked, the <code>on-click</code> attribute (which is the
<code>onSelect</code> closure action provided by <code>auto-complete</code>) is called in the
<code>auto-complete-option</code> component:</p>

<figure class='code'><figcaption><span></span></figcaption><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>
<span class='line-number'>6</span>
<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='js'><span class='line'><span class="c1">// addon/components/auto-complete-option.js</span>
</span><span class='line'><span class="kr">import</span> <span class="nx">Ember</span> <span class="nx">from</span> <span class="s1">&#39;ember&#39;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="kr">export</span> <span class="k">default</span> <span class="nx">Ember</span><span class="p">.</span><span class="nx">Component</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span>
</span><span class='line'>  <span class="p">(...)</span>
</span><span class='line'>  <span class="nx">selectOption</span><span class="o">:</span> <span class="nx">Ember</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">&#39;click&#39;</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;on-click&#39;</span><span class="p">)(</span><span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;item&#39;</span><span class="p">),</span> <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;label&#39;</span><span class="p">));</span>
</span><span class='line'>  <span class="p">}),</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<p>So where is <code>onSelect</code> defined? It is one of the block parameters yielded by
<code>auto-complete</code>, more precisely the <code>(action "selectItem")</code> action:</p>

<div>
  <pre><code class='html'>&lt;!-- addon/templates/components/auto-complete.hbs --&gt;
{{yield this isDropdownOpen inputValue
        (action &quot;toggleDropdown&quot;) (action &quot;selectItem&quot;) (action &quot;inputDidChange&quot;)}}</code></pre>
</div>


<p><code>selectItem</code> is quite straightforward:</p>

<figure class='code'><figcaption><span></span></figcaption><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>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<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>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="c1">// addon/components/auto-complete.js</span>
</span><span class='line'><span class="kr">import</span> <span class="nx">Ember</span> <span class="nx">from</span> <span class="s1">&#39;ember&#39;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="kr">export</span> <span class="k">default</span> <span class="nx">Ember</span><span class="p">.</span><span class="nx">Component</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span>
</span><span class='line'>  <span class="p">(...)</span>
</span><span class='line'>  <span class="nx">actions</span><span class="o">:</span> <span class="p">{</span>
</span><span class='line'>    <span class="nx">selectItem</span><span class="p">(</span><span class="nx">item</span><span class="p">,</span> <span class="nx">value</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>      <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;on-select&#39;</span><span class="p">)(</span><span class="nx">item</span><span class="p">);</span>
</span><span class='line'>      <span class="k">this</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="s1">&#39;isDropdownOpen&#39;</span><span class="p">,</span> <span class="kc">false</span><span class="p">);</span>
</span><span class='line'>      <span class="k">this</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="s1">&#39;inputValue&#39;</span><span class="p">,</span> <span class="nx">value</span><span class="p">);</span>
</span><span class='line'>    <span class="p">},</span>
</span><span class='line'>    <span class="p">(...)</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<p>It first calls the <code>on-select</code> action that was passed into it from the &#8220;outside&#8221;
(the controller), which just sets <code>selectedArtist</code> to the artist object
encapsulated in the list item. It then sets the <code>isDropdownOpen</code> flag to false
(which, by the mechanism seen in the previous point, closes the list) and sets
the text in the input to the item&#8217;s label (the artist&#8217;s name).</p>

<h3>Auto-completing an item</h3>

<p>As the final example, let&#8217;s see a more complicated use case. When the user
starts to type, the items that do not match the typed string will not be shown
as options. Also, the first matching item will be auto-completed and selected,
and the dropdown will be closed.</p>

<p>No surprises here, the same design principle will be applied as before. Pass
down an action that should be called from a child, then change some property
in the parent component that trickles down to the child which then rerenders
itself because of the changed attribute.</p>

<p>Let&#8217;s see the relevants parts of the template:</p>

<div>
  <pre><code class='html'>&lt;!-- tests/dummy/app/templates/index.hbs --&gt;
&lt;div class=&quot;form-group&quot;&gt;
  &lt;label&gt;Choose an artist&lt;/label&gt;
  {{#auto-complete
        on-select=(action &quot;selectArtist&quot;)
        on-input=(action &quot;filterArtists&quot;)
        class=&quot;autocomplete-container&quot; as |autocomplete isDropdownOpen inputValue
                                           toggleDropdown onSelect onInput|}}
    &lt;div class=&quot;input-group&quot;&gt;
      {{auto-complete-input
          autocomplete=autocomplete
          value=inputValue
          on-change=onInput
          type=&quot;text&quot;
          class=&quot;combobox input-large form-control&quot;
          placeholder=&quot;Select an artist&quot;}}
      {{#auto-complete-list autocomplete=autocomplete isVisible=isDropdownOpen
              class=&quot;typeahead typeahead-long dropdown-menu&quot; as |list|}}
        {{#each matchingArtists as |artist|}}
          {{#auto-complete-option
              (...)
          {{/auto-complete-option}}
        {{else}}
          &lt;li&gt;&lt;a href=&quot;#&quot;&gt;No results.&lt;/a&gt;&lt;/li&gt;
        {{/each}}
      {{/auto-complete-list}}
      (...)
    &lt;/div&gt;
  {{/auto-complete}}
&lt;/div&gt;</code></pre>
</div>


<p>We&#8217;ll start by the <code>auto-complete-input</code> this time where the <code>input</code> event,
triggered by the user&#8217;s typing, is handled:</p>

<figure class='code'><figcaption><span></span></figcaption><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>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="c1">// addon/components/auto-complete-input.js</span>
</span><span class='line'><span class="kr">import</span> <span class="nx">Ember</span> <span class="nx">from</span> <span class="s1">&#39;ember&#39;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="kr">export</span> <span class="k">default</span> <span class="nx">Ember</span><span class="p">.</span><span class="nx">TextField</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span>
</span><span class='line'>  <span class="p">(...)</span>
</span><span class='line'>  <span class="nx">valueDidChange</span><span class="o">:</span> <span class="nx">Ember</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">&#39;input&#39;</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="kr">const</span> <span class="nx">value</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">$</span><span class="p">().</span><span class="nx">val</span><span class="p">();</span>
</span><span class='line'>    <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;on-change&#39;</span><span class="p">)(</span><span class="nx">value</span><span class="p">);</span>
</span><span class='line'>  <span class="p">})</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<p>This is almost the exact copy of calling the <code>on-select</code> action we saw before
from <code>auto-complete-option</code>. Here, the <code>on-change</code> function is called that was
passed down from the block param of <code>auto-complete</code>.</p>

<p>If we take a look in the template of <code>auto-complete</code> we see it creates a
<code>(action 'inputDidChange')</code> closure action and yield that, so that should be the
next thing to look at. Here is where most of the stuff happens:</p>

<figure class='code'><figcaption><span></span></figcaption><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>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<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='js'><span class='line'><span class="c1">// addon/components/auto-complete.js</span>
</span><span class='line'><span class="kr">import</span> <span class="nx">Ember</span> <span class="nx">from</span> <span class="s1">&#39;ember&#39;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="kr">export</span> <span class="k">default</span> <span class="nx">Ember</span><span class="p">.</span><span class="nx">Component</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span>
</span><span class='line'>  <span class="p">(...)</span>
</span><span class='line'>  <span class="nx">actions</span><span class="o">:</span> <span class="p">{</span>
</span><span class='line'>    <span class="nx">inputDidChange</span><span class="p">(</span><span class="nx">value</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>      <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;on-input&#39;</span><span class="p">)(</span><span class="nx">value</span><span class="p">);</span>
</span><span class='line'>      <span class="k">this</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="s1">&#39;isDropdownOpen&#39;</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span>
</span><span class='line'>      <span class="kr">const</span> <span class="nx">firstOption</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;list.firstOption&#39;</span><span class="p">);</span>
</span><span class='line'>      <span class="k">if</span> <span class="p">(</span><span class="nx">firstOption</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="kr">const</span> <span class="nx">autocompletedLabel</span> <span class="o">=</span> <span class="nx">firstOption</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;label&#39;</span><span class="p">);</span>
</span><span class='line'>        <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;on-select&#39;</span><span class="p">)(</span><span class="nx">firstOption</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;item&#39;</span><span class="p">));</span>
</span><span class='line'>        <span class="k">this</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="s1">&#39;inputValue&#39;</span><span class="p">,</span> <span class="nx">autocompletedLabel</span><span class="p">);</span>
</span><span class='line'>        <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">&#39;input.element&#39;</span><span class="p">).</span><span class="nx">setSelectionRange</span><span class="p">(</span><span class="nx">value</span><span class="p">.</span><span class="nx">length</span><span class="p">,</span> <span class="nx">autocompletedLabel</span><span class="p">.</span><span class="nx">length</span><span class="p">);</span>
</span><span class='line'>      <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<p>We first call the <code>on-input</code> action which filters out the artists that do not
match the typed prefix. The result of that is that <code>matchingArtists</code> will only
contain the artists that do match. The dropdown is then opened to display these
items (or an explanatory blurb if none matches). If there is at least one
matching item, the first one is selected (and becomes <code>selectedArtist</code>).</p>

<p>As an UX improvement, the &#8220;inferred&#8221; range from the label in the input is
selected, so that the user can continue typing and thus select another artist if
the first one was not what they meant. (See when I type &#8220;J&#8221; in the demo).</p>

<h3>Design concepts</h3>

<p>I&#8217;m not totally happy with the current state of the component because of the
following:</p>

<p>1) The <code>auto-complete</code> component reaches inside the <code>auto-complete-input</code> one
(set in its <code>input</code> property) to call <code>setSelectionRange</code> on it (see the last
code snippet).</p>

<p>2) The same component retrieves the options from the list and gets its <code>item</code>
to select it. Again, this is quite intrusive and will break if the internals of
<code>auto-complete-option</code> change.</p>

<p>3) Still the <code>auto-complete</code> component yields an instance of itself as a block
parameter. This enables &#8220;downstream consumers&#8221; to access any of its properties
and methods, breaking its encapsulation.</p>

<p>In presenting about these concepts at the <a href="https://www.bigmarker.com/global-ember-meetup/Inside-Ember-Mirage-and-Complex-Component-Design">Global Ember Meetup</a> and at
<a href="http://www.meetup.com/Ember-js-Belgium/events/226904768/">Ember.js Belgium</a>, I said that I like to think about components as the
objects of the UI.  Thinking about them as objects helps to deliver the point
that some (most?) object oriented practices should be applied to components,
too. If this assumption is correct, we can leverage OOP design concepts and
guidelines that we&#8217;ve been developing for decades, giving us a headstart on how
to design (and what to watch out for) complex component hierarchies.</p>

<p>For example, I consider the set of block parameters yielded by a component as
its public API. This means that yielding <code>this</code> from a component&#8217;s template is
considered bad practice as it breaks encapsulation. In some cases, it&#8217;s
relatively easy to find a way around it, in others it&#8217;s much more difficult.
We&#8217;ll see if I can pull it off in the above case.</p>

<p>As a closing thought, notice how 95% of the feature&#8217;s implementation relied on
block parameters and closure actions. They are fantastic tools to work with and
I don&#8217;t know how anything could be achieved without them before they existed.</p>

<h2>Pointers</h2>

<p>Incidentally, <a href="https://twitter.com/miguelcamba">Miguel Camba</a> seems to think about components lately, too. I
already mentioned his fantastic talk at EmberCamp this year called <a href="https://www.youtube.com/watch?v=6N4qsO22fmw">&#8220;Composable
components&#8221;</a>, but above that he has released <a href="http://www.ember-power-select.com">ember-power-select</a>, which
serves the same purpose as the <code>auto-complete</code> component in my blog post series.</p>

<p>However, it&#8217;s much more mature and flexible so if you need a select dropdown in
your app, use <code>ember-power-select</code>, as my component is for learning and
demonstration purposes only. That said, I published it on Github under
<a href="https://github.com/balinterdi/ember-cli-autocomplete">balinterdi/ember-cli-autocomplete</a> if you want to take a look or follow
along the blog posts while looking at its source code. I put a tag called
<code>ccd-part-one</code> on the repo for this blog post.</p>

<h2>In the next episode&#8230;</h2>

<p>&#8230; of the series, I&#8217;d like to address (some of) my concerns I mentioned above
and see how to fix them. Stay tuned!</p>
]]></content>
  </entry>
  
</feed>
