Rails and Angular without the SPA
23 Jan 2016A full on Angular single page application (SPA) is overkill 90% of the time. This article will illustrate a simple way to get the rich user experience from javascript while still relying on Rails server rendering for the bulk of the application.
Our approach advocates the following philosophy:
Javascript and angular functionality exists to enrich the user experience of existing server-side rendered pages.
This is based on the premise that only a handful of pages actually need javascript functionality. Most of your pages are happily being rendered server side, but there’s that one page that needs sophisticated user experience (UX). For example, you might have a master-detail page, and want AJAX requests to fill the detail without navigating to a new page.
Setting up Angular with Rails
I recommend using bower-rails to manage client side dependencies like Angular. You will need to install bower, please go to bower-rails for more details if unfamiliar.
Bowerfile
Pull down the client side dependencies
Then add .js files to application.js
Setup is done.
Working With Turbolinks
If you’re using Turbolinks (you should), you’ll need to bootstrap the angular application on every Turbolinks page load.
I recommend creating an initializer.js
file with the following:
This callback will bootstrap angular on every turbolinks page navigation.
Angular Directives and Controllers
With all our setup done, we can now add Angular functionality to our pages.
There are two main ways to do this:
- Angular Controllers
- Useful when adding page specific functionality
- Angular Directives
- Useful when creating reusable widgets, such as a HTML 5 video player, that can be reused across pages.
Angular Controllers
Angular let’s you tag DOM elements with ng-controller
to associate javascript functionality with
a particular page. The key word below being UserCountsChartCtrl
:
users/index.haml.html
javacsripts/ng/controllers/UserCountsChartCtrl.js
Here I am drawing bar charts on the index page using Charts.js with an Angular Controller.
Passing data from server side to client side
One often needs to get information to the javascript client. In a typical SPA, this
is done with a subsequent AJAX call. Here we save that AJAX call and just render the information
in data
HTML attributes. Notice the lines below:
javacsripts/ng/controllers/UserCountsChartCtrl.js
This allows you to leverage Rails (controllers, presenters, etc) to present the data needed by the javascript client side.
Angular Directives
Angular Directives allow you to create javascript functionality that is cross cutting. The example below is ensures that a form can only be submitted once, to stop those pesky double click submissions.
This can now be easily used in any form:
Relying on Server Side Rendering
When making hybrid applications like this, it’s easy to get server side and client side rendering jumbled together. I advocate always using server side rendering. Sure it’s less flashy, but it’s more productive and consolidates your validations into one place.
I’ve done this many ways. We’ll start with the simplest: Angular $http GETs.
AJAX with Angular $http
AJAX with Remote Forms
Wrap up
You’re right, I got carried away at the end. But now you have an exhaustive set of examples that show how a sprinkle of Angular can breathe rich interactivity into your Rails rendered pages.
Enjoy!