Despite lack of browser support, ES6 is beginning to leave its mark on modern web development. We still have to transpile ES6 code down to ES5, but improvements in transpilers and automation make the process almost seamless. In this post I will demonstrate how to benefit from ES6 JavaScript in Angular 1.x.

There are many choices when it comes to transpiling code down to ES5 JavaScript, but in this article I will be using Babel in combination with Grunt to automate the process. Since transpiling adds extra steps to writing code it's very important to remove any manual steps and be fully automated. It turns out automation is easy to configure if you are using a task runner like Grunt. In fact we will even add a task that watches ES6 files for changes and regenerates the ES5 file whenever the ES6 files are changed..

Here are the required steps:

Note: We will be using npm to install the necessary dependencies, so you may need to install npm if you don't already have it installed.


Create a package.json file with the necessary requirements. The version numbers may change over time, so feel free to update as new versions are released.

{ "dependencies": { "grunt-babel": "^5.0.0", "babel": "^5.1.8", "grunt": "~0.4.5", "grunt-contrib-concat": "^0.5.1", "grunt-contrib-watch": "^0.6.1" } }

Run npm install


Grunt, the task runner requires some configuration in order to run the various tasks needed to watch and transpile code. Add the following Gruntfile.js

module.exports = function(grunt) { grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), concat: { dist: { src: ['src/greetingService.js', 'src/personService.js'], dest: 'dist/combined.js' } }, babel: { options: { sourceMap: true }, dist: { files: { "dist/app.js": ['dist/combined.js'] } } }, watch: { files: 'src/*.js', tasks: ['concat','babel'] } }); grunt.loadNpmTasks('grunt-contrib-concat'); grunt.loadNpmTasks('grunt-contrib-watch'); grunt.loadNpmTasks('grunt-babel'); grunt.registerTask('default', [ 'concat', 'babel', 'watch' ]); };

Don't worry too much about the details of Gruntfile.js, but the high level summary is that we define tasks to combine all ES6 files into a single file before running the ES6 to ES5 conversion. Lastly we are adding a watch task for rerunning the tasks when individual files change. The final output of the process is a combined ES5 JavaScript file.

Sample ES6 files to transpile

class PersonService{ constructor(){ } getPerson(){ return 'Jim Smith'; } } angular.module('app').value('PersonService', PersonService); class GreetingService{ constructor(){ } sayHello(){ return 'Hello from ES6!'; } } angular.module('app').service('GreetingService', GreetingService);

I have added two example files that are also referenced in Gruntfile.js. Pay attention to the last line in both files as it sets up two different Angular providers that will be used to inject the generated services into our Angular sample controller.

angular.module('app').controller('greetingController',[ 'GreetingService', 'PersonService', function(GreetingService, PersonService){ var vm = this; vm.greet = function(){ var personService = new PersonService(); vm.person = personService.getPerson(); vm.greeting = GreetingService.sayHello(); }; }]);

I purposely defined both an Angular service and an Angular value in order to demonstrate two different ways to integrate the code in the controller. As you can tell the service provider (GreetingService) is instantiated for us by Angular, so there is no need to call new to create an instance. The value provider (PersonService) is different since it passes in the raw constructor instead of an instance. This means we have to “new-up” the service before using it.

The only thing you have to do now is type grunt on the command line to kick things off

Anyway, there you have it. Adding ES6 to Angular 1.x is pretty straight forward.