Skip to content
Sep 24 14

How Ember.js Components communicate using sendAction

by cory

Components and sendAction

Some people find the use of `sendAction` in Ember components a bit confusing. In this post I'll go over how Ember component use `sendAction` to communicate with controllers and routes, with some examples of common pitfalls.

(P.s. For more info on many other Ember pitfalls see the Emberfest 2014 Presentation by @alexspeller. It inspired me to write this post.)

There are several ways using actions in an Ember component is different than in a route or controller:

1. In an Ember component, unlike an Ember controller or route, you use `sendAction`. (In a route or controller you would just use the `send` method.)

2. In an Ember component, unlike an Ember controller or route, if you call `sendAction` and there is no handler for that action, no error is raised. (In a route or controller Ember would complain with a error message that starts with: "Nothing handled the action:".)

3. The component's `sendAction` is intended to send an action using the component's name for that action. The outer context (controller or route) might have a different name for the same action. The handlebars template is the place to specify the name of the action on the controller/route that will be invoked when the component calls `sendAction` with its name for that action.

Example: {{date-picker}}

As an example, say we have an imaginary {{date-picker}} component. Its semantic name for the action that it sends when a user has selected a date is "pickedDate". The controller context in which this component is being used will have its own name for the action it wants to take when the {{date-picker}} component sends it its "pickedDate" action. In this example, we are using the {{date-picker}} to allow a user to select their birthday, so the action on the controller is "setBirthday". We connect the "pickedDate" component's action to the controller's "setBirthday" action in the template:
{{! index.hbs}}

Pick a date:
{{date-picker pickedDate="setBirthday"}}

Note that the action that the component exposes (`pickedDate`) is on the left side of that assignment, and it is unquoted. The action name on the controller is quoted: it is the literal string value "setBirthday". The way I think of it is that `pickedDate` is a property of the component, and we want to set that component's property to the name of an action on the controller. We have to put quotes around "setBirthday" in the template because we actually do want the `pickedDate` property to equal the literal string "setBirthday". If there were no quotes around "setBirthday", Ember would treat it as a property and replace it with the value of a property named `setBirthday` on the controller, which wouldn't be what we want.

And what does the code inside the component look like, to send this action to its target? Here is a stripped-down example, leaving out the code that the component might use internally to draw a calendar, respond to user clicks/keypresses, etc. We'll assume that that part of the component works and when the user has finished selecting a date the component internally triggers its own action `donePickingDate`. In that case, the code looks like this:
// components/date-picker.js

export default Ember.Component.extend({
  actions: {

    // this is the action that the component handles
    //*internally* when the user has picked the date.
    // The name of this action could be anything that
    // the component author chooses, since it won't
    // be exposed to the outside world.
    donePickingDate: function() {

      // we assume that some other code in the component
      // has correctly set the `theDate` property
      // by this point.
      var theDate = this.get('theDate');

      // Here we communicate to the *outside* of
      // the component, sending our semantically-named
      // "pickedDate" action to the outside world.
      //
      // In index.hbs we had specified that the `pickedDate`
      // property of this component equals "setBirthday".
      this.sendAction('pickedDate', theDate);
    }
  }
});

It can be complicated to keep the various actions, action names and sendAction calls straight. It begins to get clearer if we start by remembering that a component is intended to be isolated from the rest of our application. It can be easy to forget this because most of the time we use components we are writing them ourselves, but in an ideal world we would have many third-party components that we could drop into our Ember app which we would treat as black boxes.

So, if we consider our component (whether we wrote it our not) to be a black box, we can think of it as having an "action API surface", by which I mean an action or set of actions that it provides to us, the consumers of this component. When using the component, it is our responsibility to specify how our app should respond to each of the action(s) the component exposes. This is what we are doing in our template when we specify `pickedDate="setBirthday"`. We wouldn't want the {{date-picker}} component to need know anything about what we intend to do with the date that the user has selected. It just sends an action that a user picked the date, and the outside context does the right thing with that date. Otherwise we'd need a different version of the component for every context we wanted to use it in ({{date-picker-for-birthday}} that sends 'setBirthday' action, {{date-picker-for-due-date}} that sends 'setDueDate' action, etc.), and we'd lose the reusability that components are designed for.

tl;dr: The component calls `sendAction` with its preferred name for the action, and Ember translates this into the controller's preferred name for the action, which was specified (as a string) in the template.

index.hbs 2014-09-24 15-29-59

The way Ember does this translation internally is when the component calls `this.sendAction('pickedDate', theDate)`, Ember looks up the value of the `pickedDate` property. In this case that value is the literal string "setBirthday". Ember then invokes that action on the controller. Because of the way `sendAction` works, if there is no handler for the "setBirthday" action on the controller or its parent route(s), there will be no error raised and Ember will silently do nothing.

It's worth noting that the action that the component sends is distinct from the properties in its own `actions` hash. It can be confusing because in most cases, the name of the action that the component sends will not be very prominent in the component's own code. It will usually only appear that one time, as a string, in the component's `this.sendAction('pickedDate', ...);` call. The component must rely on the template having set a value for `pickedDate`. Couple this with the fact that `sendAction` will not raise an error, and it's easy get confused when using a component. Consider this template and component:
{{! index.hbs}}

Your birthday?
{{date-picker}}
// component/date-picker.js
Ember.Component.extend({
  ...
  actions: {
    donePickingDate: function(){
      ...
      this.sendAction('pickedDate', theDate);
    }
  }
});

What happens when the user has finished selecting a date? Nothing. No error will be raised. The component will happily send an action named `undefined` (because the value of its `pickedDate` property was never specified in the template), and since there is no handler for an action named `undefined` in the controller or route hierarchy, `sendAction` will silently ignore it and do nothing.

Component Reuse

If you consider using the same component more than once in a template, you can see another reason that it makes sense to specify the controller's action name in the template. For example, say we have a template where a user is trying to pick her birthday *and* set a deadline date for a to-do item:
{{! index.hbs}}

What is your birthday?
{{date-picker pickedDate="setBirthday"}}

When is this to-do due?
{{date-picker pickedDate="setDueDate"}}

In this case, we have two different actions on the controller ("setBirthday" and "setDueDate") that we want to handle the date picker's `pickedDate` action in two different parts of the template. The component code is the same: in both cases, it will just call `this.sendAction('pickedDate', ...)`, and Ember will translate that into the correct action on the controller depending on which part of the template the user was interacting with.

sendAction's default action name: "action"

So far our example using {{date-picker}} has focused on it having a semantically-named "pickedDate" action. Accordingly, we've been having the date-picker component explicitly name that action in its code when we call `this.sendAction('pickedDate', ...)`. However, since many components have a clear single action that they take, Ember provides a convenience by defaulting to sending an action named "action". You could see how this would be convenient if you imagine we are picking components out of a library of potential components. We have {{date-picker}} and {{date-and-time-picker}} and {{time-picker}}. Rather than each of them implementing a different named action ("pickedDate", "pickedDateAndTime", "pickedTime"), the convention is that they will all simply send an action named "action", and so we can specify in our template what action each should take:
{{! index.hbs}}

Birthday?
{{date-picker action="setBirthday"}}

When do you wake up?
{{time-picker action="updateWakeTime"}}

When is this to-do due?
{{date-and-time-picker action="setDueDate"}}

In theory, since "action" is the default action name for `sendAction`, our component code would simply call `this.sendAction(theDate)` without specifying the action name. However, there's an important caveat which is that when you are sending a default action that includes a parameter(s), Ember has no way of telling the difference between this and sending an action by its name. So even if you are sending the default action, if you are including a parameter(s), you must still use "action" as the first parameter: `this.sendAction('action', theDate)`.
Jul 13 14

Physics Simulations with Ember

by cory
I saw this cool javascript simulation of a double pendulum by @MicaelOl on hacker news the other day, and aside from taking me back to my Classical Mechanics class in undergraduate many years ago, it inspired me to try to do the same with Ember and SVG.

As a first stab, I made a single pendulum aka a Harmonic Oscillator:
{{ember-pendulum}}
And then after a little messing around with it (and copy-pasting the equations verbatim from the original javascript sim), I got an Ember double pendulum simulation!
{{double-pendulum}}
When I was an undergraduate I toiled on a final project related to the Lagrangian for my Classical Mechanics for a couple weeks, and a large part of that was programming a double-pendulum simulation in a java applet. It took me about 2 weeks to make it back then. When I tried to do this in Ember it took me about 1 hour. That's progress.
Jul 10 14

Demystifing Ember Async Testing

by cory
I've been using Promises in my ember code for long enough now that I've started to internalize how they work. So, when I started writing acceptance tests using the ember async test helpers (`visit`, `click`, and so on), I assumed that since those helpers are referred to as "async helpers", they would be promises and I should chain them all together in my test to ensure that the asynchronous activity all happens in the correct order. I understood that ember's testing framework is now promise-aware, and I presumed that meant it would notice when the return value of my test was a promise, and wait for that promise to settle before finishing the test.

I started out writing test code like this:
test('visiting the index page', function(){
  return visit('/').then(function(){
    return click('button#success');
  }).then(function(){
    // all async activity from the IndexRoute and
    // clicking the success button will be finished
    // by now
    equal(currentURL(), '/success');
  });
});


[Note: This article assumes some familiarity with Javascript Promises. If you're not familiar with them, there are many resources online to learn, including an article I wrote about them that includes an interactive demonstration of promises in action.]

This should look familiar if you're comfortable with promises. Each promise-returning function (`visit`, `click`) is chained via a `.then` call to the next, ensuring that the `visit` promise is settled before we attempt the `click` promise, and so on. Test code like this works just fine, but it is a bit verbose.

Ember's Test Helpers are Fake Synchronous


What I didn't realize originally is that Ember's async test helpers are much smarter than I gave them credit for. In the Test Helpers section of the Ember Guides, this example test code is shown:
test('simple test', function(){
  expect(1);
  visit('/posts/new');
  fillIn("input.title", "My new post");
  click("button.submit");

  andThen(function(){
    equal(find("ul.posts li:last").text(), "My new post");
  });
});

What! If that code isn't at least lightly blowing your mind, then you either understand Ember's testing helpers better than I did, or you may not be paying close enough attention. I'll illustrate with an example. We want to ensure that the `fillIn` call is not made until the `visit` call has finished (which could take an arbitrary amount of time, due to the fact that it may involve fetching data from an API), and likewise that the `click` call isn't made until the `fillIn` operation has finished. And, finally, any action that Ember takes as a result of clicking "button.submit" (which could involve sending data to an API and/or a route transition) is also finished before the `andThen`'s anonymous function containing our test's assertion is called.

Naive Promise-Returning Test Helpers


Let's take a stab at writing our own pseudo versions of the promise-returning `visit`, `fillIn`, `click, and `andThen` helper functions:
function visit(url){
  return new Ember.RSVP.Promise(function(resolve, reject){
    var timeout = Math.random() * 50; // arbitrary delay
    Ember.run.later(function(){
      // route-visiting code such as `beforeModel` etc
      // would go here
      console.log('Finished visiting ' + url);
      resolve();
    }, timeout);
  });
}

// assume fillIn, and click are defined similarly

// Now, run these lines:
visit('/posts/new');
fillIn("input.title", "My new post");
click("button.submit");

// Console output:
// (All three statements run at essentially the same time,
//  finishing in a non-deterministic order)
// 'Filled in input.title with My new post' <-- 2nd promise finishes first
// 'Clicked button.submit' <-- 3rd promise finishes before 1st
// 'Finished visiting /posts/new' <-- 1st promise finishes last

Here is a live example showing what happens if we take the naive approach described above. As you can see, just because the `visit`, `fillIn`, and `click` method calls are on subsequent lines, this does not guarantee that their promises resolve in that order. All three helpers start nearly at the same time (you'll see the "1a", "2a", and "3a" log lines appear nearly instantly), but they finish in a random order.
Ember Async Test Helpers Part I

Now it should be somewhat clearer why Ember's test helpers are mysterious. How can Ember ensure that the `fillIn` method call only happens after the `visit` one is done, if we haven't explicitly chained them together? In a normal javascript context, you cannot delay execution of a line based on a previous line. Javascript is non-blocking, so each line executes as soon as the previous one has, even if the previous line has asynchronous behavior that isn't finished yet. This is different from some other languages you probably use. In Ruby, for example, if you had a line that requested data from the database (e.g., `user = User.find(1)`), the execution of the next line of ruby would block waiting until the database had returned its data, and on the next line you could reference the `user` variable, knowing that it had been fully hydrated from the database.

This is not the case for javascript, however, and it is why we used chained promises when we need to guarantee the order of asynchronous method calls. We cannot get away from the need to chain these calls together, but we can get away from explicitly chaining them together, if we are clever.

Context-Aware Test Helpers


Let's redefine our versions of the `visit` and other async helpers. Now, instead of simply returning a promise, they will detect the presence of a global, shared-context promise, and automatically chain themselves to that if it exists. If it doesn't exist, they'll create it and then chain themselves to it. Now our `visit` function, for example, will look like this:
function visit(url){
  // create the shared promise
  // if it doesn't exist
  if (!window.sharedPromise) {
    window.sharedPromise = Ember.RSVP.resolve();
  }

  // chain our code to the shared promise
  window.sharedPromise = window.sharedPromise.then(function(){
    // this is the original `visit` code:
    return new Ember.RSVP.Promise(function(resolve, reject) {
      // ...
      // simulate delay and then call `resolve`
      // ...
    });
  });
}

Visually, this is what is going to happen now:
async-test-helper-animation
Here is a live example showing these global promise-aware pseudo test helpers in action: Ember Async Test Helpers Part II

Putting it all together


As it turns out, this is almost exactly what Ember's testing helpers do! The Ember testing code maintains a shared promise (stored on `Ember.Test.lastPromise`) that it chains each additional async helper call onto. This is the relevant code snippet:


The Ember testing code does a few additional things (such as attempting to resolve nested async promises properly), but at a high level all it is doing is using a shared promise global variable to chain each async helper onto. This is how Ember testing helpers allow you to write code with asynchronous behavior but write it in a synchronous style, without having to explicitly think about promises or promise chains.

At this point you may be wondering how Ember actually knows that the `visit` (or `click`, etc.) async helper has finished all its async behavior. So far we've assumed that the `visit` helper returns a promise that resolves when its async activity is finished, but we've glossed over the actual mechanism by which Ember ensures the promise resolves at the proper moment. The answer to this is that Ember internally uses a heuristic for async activity that involves checking for run loop activity, pending ajax requests, router activity, and more, but that is a subject for a later blog post. Please follow me (@bantic) on Twitter to hear about future posts.

Summary

The one takeaway here is that when writing integration tests in Ember, every line of your test should be an async helper or the anonymous function passed to `andThen`. That is, every line of your test should be one of `visit`, `fillIn`, `click`, etc., or an `andThen` call, or inside of the `andThen`'s anonymous function. If you do this, the async-aware nature of Ember's testing code will allow you to write simple, clean tests and be confident that the code will run in the correct order, without having to clutter your test code with explicit asynchronous control flow.

Need Ember.js Testing Help? Hire us!

If your company needs help writing solid tests with Ember, my Ember.js consulting company, 201 Created is available for hire. Please get in touch!
Apr 6 14

Hand-Crafted HTTP with Telnet: Exploring the protocol

by cory
I've been reading Ilya Grigorik's truly excellent High Performance Browser Networking lately and as I went through the HTTP section I realized that there were some gaps in my understanding of the protocol.

Fortunately, the HTTP 1.1 protocol is text-based, so we can create HTTP requests very easily by hand using telnet! The HTTP version 1.1 protocol is laid out in RFC 2616. It can look fairly intimidating at first but it's actually quite readable. At a high level, HTTP, which stands for Hypertext Transfer Protocol, outlines a mechanism for clients and servers to communicate to transfer resources (the R in URL) from one server to another. Your web browser is an HTTP client and it retrieves resources (HTML documents, CSS files, javascript files, images, etc) from HTTP servers.
If we want to make an HTTP request by hand, the most important place to start is Section 5 of RFC 2616, which explains how a client makes a request to a server. The format is, roughly:
Request-Line
Header line(s)
CRLF (empty line)
Message body (optional; for example if POSTing data)
What does Request-Line mean? The spec explains. Here it is, verbatim, where "SP" means whitespace.
Method SP Request-URI SP HTTP-Version CRLF
You're already familiar with the possible values for "Method" (GET/POST/PUT/etc). Request-URI is basically the url path that you are requesting (i.e., if you are asking for the root url, it is "/"). The http version is going to be 1.1, which is written as "HTTP/1.1".

So, to request the root URL at the server via GET, you would use this as the request line:
GET / HTTP/1.1
So far so good. The next part of the request is the headers. The full range of possible headers are described in Section 14. Suffice it to say for now that the headers are where you can include additional metadata about your request, such as your client's user-agent, the content-type, the language, caching options, and so on. The only one that is required by HTTP/1.1 is the "Host" header, which must match the address of the server that you are requesting the resource from. To request the homepage from google, then, this is the HTTP request text we would need to use.
GET / HTTP/1.1
Host: google.com
CRLF (empty line)
For example, say we have this very simple "Hello, World" node server, running on localhost at port 5000:

Here is what it looks like to connect via telnet and request the url "/":

telnetsimple
You may notice a couple things. First of all, as soon as an empty line (CRLF) is entered after the last header, we get back the server response. HTTP also defines a specific way for an HTTP server to respond, and it is fairly similar to the format of a client request. There's an initial line that includes the HTTP version and the status code ("HTTP/1.1 200 OK"), then some header lines, then a blank line (CRLF), then the message.

But why does it say "c" before the "Hello, World" text and "0" afterward? That wasn't part of our server's response, was it? That looks like random junk. Well, if you look at the headers again you'll notice that one of them specifies "Transfer-Encoding: chunked". Chunked Transfer Encoding wasn't in the HTTP/1.0 spec but has been added to the HTTP/1.1 spec. Chunked transfer encoding allows a server to send responses in, well, chunks, rather than doing it all at once. The HTTP spec says that before each chunk the server must send a line with the length of the following chunk (in hexadecimal), and a line with "0" on it after the chunk. If you count up the letters in "Hello, World" you'll get 12, which happens to equal "c" in hexadecimal.

Finally, if you're paying close attention you may further notice that the telnet session didn't end after the server sent us the "Hello, World" response. This is due to another change that was introduced in HTTP/1.1: persistent connections by default. In order to cut down on the latency overhead that is incurred by the TCP connection handshake, in HTTP/1.1 all connections are, by default, kept alive so that the client can request another resource without needing to re-connect. The server indicates that it intends to keep the connection alive by adding the "Connection: Keep-Alive" header to its response.

If we do not want this behavior, we can explicitly tell the server to close the connection by adding the "Connection: Close" header to our initial request. Here's an example of that:

telnetsimple-close

This time, the connection is immediately dropped by the server after it finishes responding.

Remember how I mentioned that the Host header is required by HTTP/1.1? Why would it be required? Shouldn't the server know what Host is being requested? The answer is, surprisingly, that it does not. The HTTP/1.0 standard assumed that one IP address was equivalent to one server, but we now have the concept of a multi-homed server, which just means that a single server at a single IP address can serve multiple domains. Without the Host header, a server running HTTP/1.0 can't tell which of the possible hosts should handle the incoming request.

In the follow-up to this post I'll look into how to hand-craft an HTTP request that actually sends data to the server. If you've ever wondered how the data in a form actually gets to the server, we'll go into that.
Feb 24 14

How does Release Date Affect Oscars Best Picture Wins?

by cory
I was looking for an excuse to play around with d3, and since the Oscars are coming up next weekend, I put together a little d3-powered chart showing the number of best picture wins by US release month.

If you're just here for the answer to the title question, it is: Quite a bit. About 25% of the winners were released in December, and over half were released in the 3 months at the end of the year.

I used the enjoyable and optimistic-sounding Cheerio npm module (DOM traversal/selection a la jQuery, but in node.js) to scrape , and followed along with Mike Bostock's gentle d3 bar chart tutorial to put the data together in jsbin.

Here are the results:
JS Bin

I was hoping to do a little more explanation of how this was generated, but I'll save that for a future post. The code is pretty quick-and-dirty, anyway. If you'd like to do something with the cleaned-up data, the movies.json file is on github.

What did I learn? Well, not a whole lot. My initial expectation was that the movies were released toward the end of the year. In retrospect, even though it seemed official, the Oscars.org best picture winners page was probably not the best one to use. I should have been clued in by the raw php code in the source HTML there. It seemed marginally easier to parse than Wikipedia, though, so I went with it, but the extra time spent cleaning up data by hand offset any gains.

I was a bit surprised to realize how complicated release dates can be. The same movie gets released multiple times in the same country, and also in other countries, and also sometimes gets re-released. I had to put together some simple heuristics to choose the most appropriate date from lists like this one for The Sting.

Not-too-surprising fact: Lots of movies sneak in a limited release somewhere late in December but aren't available widely in the US until the following year (like Million Dollar Baby, which had a limited release in mid-December and the wide release about 7 weeks later).

Most surprising thing: Casablanca appears to be the only film listed to win for a year other than the one in which it was released. According to IMDB it was released in 1942 yet somehow won the 16th Academy Awards in 1943. Perhaps the notion of 'release date' is even looser than I realized.