Utils and Helpers allow you to have reusable code in your templates and your JavaScript files. Helpers are for your templates and Utils are largely for your JavaScript files. In both cases, they are largely just functions. Once again today we are going to be using Ember Twiddle to look are these concepts.

First we are going to create a helper that we can use in our template. The most common use of helpers is probably to format some number of property, however, as they are just functions their possible applications are limitless. To generate a helper in an EmberCLI project you would just type ember g helper some-helper.

But, since we are using Ember Twiddle we will just hit new, then add, then helper. Let's name our helper activity-label. We want our helper to take a name and return the name titlecased with the word Activity at the end. For our purposes, let's just assume we will only have one word titles. Our helper will look like this:

import Ember from 'ember';

export function activityLabel(params) {
  let name = params[0];
  return `${name[0].toUpperCase() + name.substring(1)} Activity`;
}

export default Ember.Helper.helper(activityLabel);

One important thing to note is that the arguments that you pass in to your helper from your template are passed to the function as an array, so we will get the first argument passed in then get the first character of that string and capitalize it, add back the rest of the string, then add the word 'label'.

Now, to use our helper in a template we just include it as we would a component.

{{activity-label 'hello'}}

As you can imagine we can do all sorts of things with these helpers. Let's make an addition helper. Just create a helper called add.js:

import Ember from 'ember';

export function add(params) {
  return params.reduce((arg1, arg2) => arg1 + arg2);
}

export default Ember.Helper.helper(add);

We will just use reduce on the params and add each of the params together. Then we can call it in our template as:

{{add 2 3 4 6 6}}

And we can add as many values as we like there. You may also notice that where components require a dash in the name, helpers do not have this requirement. So what if we have a name collision between a helper and component? Well, the component will win and as far as I know there isn't any good reason for this it is just how it is. It also worth noting that, as helpers are just functions, they are composable.

Let's create a multiply helper to see this in action.

import Ember from 'ember';

export function multiply(params) {
  return params.reduce((a, b) => a * b);
}

export default Ember.Helper.helper(multiply);

Then in our template we just add parentheses and call our new helper:

{{add 1 2 (multiply 2 2 2)}}

So that is it for helpers, now lets look at utils. Like helpers, in an EmberCLI project you will just generate your utility functions by typing: ember g util someUtil.

Here, let's just create a new util, we are going to use our utility to format height. So, let's call it height-format. In Ember you have to manually import utils, so in Ember Twiddle we can just create an Other. Then add our util code:

export default function heightFormat(height) {
  let feet = Math.floor(height/12);
  let inches = height % 12;
  if(!!inches){
    return `${feet}' ${inches}" `;
  } else {
    return `${feet}' `;
  }
}

Then we will import it into our application controller. Then we will create a height property which will be in inches, then we will create a computed property that will call our heightFormat function and return the formatted height. Obviously in this case we don't have to have a separate util, but if we are going to reuse this code in several places this prevents duplication. Also of note the import path here is relative, so it would be different depending on your specific situation.

import Ember from 'ember';
import heightFormat from './../height-format';

export default Ember.Controller.extend({
  appName: 'Ember Twiddle',
  height: 73,
  formattedHeight: Ember.computed('height', function(){
    return heightFormat(this.get('height'));
  })
});

Finally, we can just call our formattedHeight property in the template and everything works as we would expect. Let's also add an input for the height property {{input value=height}} and we can see that our formattedHeight function works nicely.

That is it for today. Tomorrow we will look at a few other template helpers. See you then.