Angular Templates in Rails Using Sprockets & JST

There are a number of different ways to get templates into your Angular app built on Rails. I've come across a method I'm quite fond of and figured other folks might benefit from seeing a basic example of how I went about it in my current project.

When you're building apps with Rails, you have access to the (awesome) Asset Pipeline which uses Sprockets. If you include the EJS or Eco gem in your project, Sprockets allows you to save client-side templates that will be available via the JST global namespace. For example, given the following folder structure:

-- app
  -- assets
      -- javascripts
        -- application.js.coffee
        -- app.js.coffee
      -- stylesheets
      -- templates
         -- index.jst.eco
  -- controllers
  -- models
  ...

You'll notice that apart from the typical Rails structure, I've added a folder (templates) and a new file (index.jst.eco). I prefer Coffeescript so I use Eco -- feel free to use EJS instead. Inside index.jst.eco we have a basic template:

<div class="container">
  <h1>{{message}}</h1>
</div>

Once we've created a template, let's go to where our Angular app is defined:

# app.js.coffee
@app = angular.module 'myApp', ['ngRoute']

# Push all templates into templateCache
run = ($templateCache, $window) ->
    templates = $window.JST
    for fileName, fileContent of templates
      $templateCache.put(fileName, fileContent())

@app.run ['$templateCache', '$window', run]

In the code above, we're taking all the templates that Sprockets compiled and placed at window.JST and pushing them into Angular's $templateCache. This makes all of our templates pre-cached and available to ngRouter's templateUrl option and ngInclude without having to fetch the HTML with another request. For example:

<div ng-include src="templates/index"></div>

The above code would include the template we created earlier, without having to fetch it. Nifty.