Series: Tables of Data

Sort Arrows (and refactoring into a component)

Published on Mar 15, 2015

Make the sorting interface more flexible. Along the way we'll cover components, tagName, actions, and displaying unicode.




Today, we’re going to be building on the sorting that we created last time. We’ll first create arrow buttons so that we can easily choose the direction we want the page to be sorted in in one click. Then we’ll refactor those into a nice DRY component.

So first, let’s get the arrow graphics. I got them from amp-what, a site for searching unicode. Let's put in the unicode codes as properties. Then we’ll display our arrows. We’ll start with the down arrow... But oops, it seems to just be showing the unicode string, so let’s use a triple mustache to return unescaped html. And we have our arrow. We can repeat this with the up arrow.

To get these to work like we expect, we’ll need to change our sortBy action. Let’s move our action from the header to the arrow button, and then let’s specify true or false for sortAscending. Then in our postsController we can change the action to take the sortAscending parameter, then set the sortAscending property on the controller based on it. It works! Now let’s repeat it for the rest of the columns.

This is an improvement on the last iteration, but there are two problems. First, there’s a lot of code to create a new column. Second, there’s no visual feedback to tell you which sort is in effect. Fortunately, components can solve both of those problems.

Let’s start by considering what we want our component call to look like. Let’s call it sortable-header. We see that there are two differences between all four iterations of the sort arrows. They are the title and the sorting property. So let’s pass those in as variables. We’ll also pass in sortBy as our action, since we’ll need to propagate it out of the component. We’ll repeat that for all four headers. This code is way shorter and more readable! But it’s also not implemented yet.

To create our component, we’ll go to the command line and use the generator.

Then we’ll go to the template and paste in what we had from before. We’re going to use our title variable to replace Updated, and our sortProperty variable to replace updatedAt in the action. If we try to look at our page, we’ll see that there are a couple of problems.

First, the arrows don’t show up. Second, all the headers are stacked on top of each other. Third, if we click on one of the buttons, we’ll get an error that says there is no action handler for sortBy. We’ll tackle those one at a time.

First, the arrows aren’t showing up because the upArrow and downArrow properties are on the controller and not the component, and components do not receive any properties from the controller except those that are explicitly passed in. Let’s take the arrow code properties, cut them from the controller, and paste them into the component. Our arrows show up.

Our headers are still stacked, and that’s because you’ll see that the table headers are wrapped in a div. Components have a tag, and it’s div by default. Let’s override that and have a tagName of ‘th’. That means we can remove the th from the template. The table headers are how we expect.

Finally, let’s add an action to the component. We’ll take in two arguments, then just send them up the chain to the action in the controller. Notice that in the component we use ‘sendAction', whereas in controllers and routes we use ‘send’. And it’s back to working like we expect.

In this episode we added a feature, noted its verbosity, then abstracted it away to a component. In the next episode, we’ll take advantage of our component architecture and use it to add a visual indicator of which sorting method is selected. I’ll see you then.

Tables of Data

Subscribe to our mailing list