by Juan Pablo Novillo Requena on October 17, 2013 // Short URL

Move logic to the front end with AngularJS

How to speed up Drupal by migrating server-side logic to the browser

At Lullabot, we always aim to make sites as performant and maintainable as possible. Recently, we've started to decouple bits of logic from Drupal and move them to the client's browser using JavaScript.

Let's look at an example. We want to display the weather of a given city in our website. This involves:

  1. Calling a public API with some parameters. We have chosen OpenWeatherMap for this example.
  2. Extract weather data from the response.
  3. Show the data in the browser.

The result would look like the following:

In Drupal, we could create a block that uses drupal_http_request() to fetch the data, then passes its results to a theme function that renders it. That is simple and maintainable, but why does Drupal needs to take care of this? There is no database involved, nor session management. If our site relies on caching to improve performance, we'll have to clear that cache whenever the block's content is updated.

Instead, let's move this to pure JavaScript and HTML so the client's browser will be the one in charge of fetching, processing and caching the data.

Meet AngularJS

AngularJS is an MVC JavaScript framework which elegantly separates controller, business and model logic in your application. Although there is a lot to learn, it removes a lot of backend logic in our Drupal projects and we've had wonderful success with it so far.

The full example can be found at Let's go through its flow together.

Bootstrapping our AngularJS application

Let's start by adding a directive to bootstrap our AngularJS application. Add the following attribute to your html.tpl.php file:

<html data-ng-app="myapp" xmlns="" xml:lang="<?php print $language->language; ?>" version="XHTML+RDFa 1.0" dir="<?php print $language->dir; ?>"<?php print $rdf_namespaces; ?>>

The attribute data-ng-app="myapp" is telling AngularJS to bootstrap our application named "myapp". For the moment this is all we need, so let's move on. We will implement our AngularJS application later.

Rendering the skeleton in Drupal

Our custom Drupal module contains some simple code that implements a block. The mymodule_block_view() function also includes a JavaScript file (the AngularJS controller) and a template which holds the markup that the AngularJS controller will use:

* Implements hook_block_view().
function mymodule_block_view($delta = '') {
  $block = array();

  switch ($delta) {
    case 'weather':
      $path = drupal_get_path('module', 'mymodule');
      $block['subject'] = t('Weather status');
      $block['content'] = array(
        '#theme' => 'weather_status',
        '#attached' => array(
          'js' => array(
            $path . '/mymodule.js',
  return $block;

That is all that Drupal will do; build the foundation.

Processing in the browser

When the page is delivered to the client, the AngularJS controller will kick in early to fetch the data from OpenWeatherMap, then process it for the view:

* Renders the weather status for a city.
var app = angular.module('myapp', [])
.controller('MyModuleWeather', function($scope, $http, $log) {
  // Set default values for our form fields.
  $ = 'Madrid';
  $scope.units = 'metric';

  // Define a function to process form submission.
  $scope.change = function() {
    // Fetch the data from the public API through JSONP.
    // See
    var url = '';
    $http.jsonp(url, { params : {
        q : $,
        units : $scope.units,
        callback: 'JSON_CALLBACK'
      success(function(data, status, headers, config) {
        $scope.main = data.main;
        $scope.wind = data.wind;
        $scope.description =[0].description;
      error(function(data, status, headers, config) {
        // Log an error in the browser's console.
        $log.error('Could not retrieve data from ' + url);

  // Trigger form submission for first load.

Rendering the results

Our template simply references our controller (that is how AngularJS does the binding) and outputs the variables we set in the $scope object previously.

<div ng-controller="MyModuleWeather">
  <label for="city">City</label>
  <input type="text" ng-model="city" /></br>
  <label for="units">Units</label>
  <input type="radio" ng-model="units" value="metric"/> Metric
  <input type="radio" ng-model="units" value="imperial"/> Imperial</br>
  <button ng-click="change()">Change</button>
  <p>Temperature: {{main.temp}}</p>
  <p>Wind speed: {{wind.speed}}</p>

There you have it! We have a fully functional block that is processed in the browser. If we apply this pattern to other frequently-changing blocks on the page, we'll be able to simplify the work that Drupal does, make the page's caching more efficient, and achieving better performance. You can even use this pattern to lazy load content that varies from user to user, making the rest of the page easier to cache.

On consuming external APIs

Whenever you are building a page on one domain and requesting data from another in the client's browser, remember that browser security mechanisms can sometimes stand in the way. There are two popular ways of overcoming this. One is through Cross-Origin Resource Sharing: of course, there is a module for that on The other method is using JSONP. That's the method we used in this example, and it is supported by AngularJS and JQuery.

Why not build it with jQuery?

Technically, it is possible to build the same functionality using JQuery. However, it would require more code: you would have to take care of hiding the template while the page is being built, define a listener for the submit button, sanitize data, and bind it to the template yourself. Even with such a simple example, AngularJS offers a simple, more structured approach. It's also possible to use jQuery within AngularJS code.

Here you can find a jQuery version of the example. Have a look and compare both implementations.

Next steps

Start playing with AngularJS.
Try the AngularJS plugin for Chrome.

Juan Pablo Novillo Requena


Want Juan Pablo Novillo Requena to speak at your event? Contact us with the details and we’ll be in touch soon.


Add Your Comment


why ow why ?!

why does people choose to write such ugly lines in javascript : var app = angular.module('myapp', []) .controller('MyModuleWeather', function($scope, $http, $log) {

and this $http.jsonp(url, { params : { q : $, units : $scope.units, callback: 'JSON_CALLBACK' }}).

there is no reason, you can break that line to much more readable clear code . javascript is great, but people who write javscript usually are very bad programers .




If you have a problem with it please post another way of writing the code so that everyone can benefit.



yes ... really .

var app = angular.module('myapp', []); app.cont = function($scope, $http, $log) { }; app.controller('MyModuleWeather', app.cont); var params = { q : $, units : $scope.units, callback: 'JSON_CALLBACK' }; $http.jsonp(url, { params : { params });

it seems your comments doesn't support markdown code block ...



bad code

this is clearly bad writing by most basic standards, and i don't understand why javascript community continue to adopt this style .

first you can't document such code .

second you have parenthesis that ends one inside the other at the end of file in very ugly way which make syntax unreadable

third it creates dependency in different sections of unrelated code, for example if you have error in function body then it is difficult to reach and identify it using debugger because you need to enter other layers of wrapping function calls and object instantiating .



simple javscript

i believe people used to write this style of one line code because they used to do very simply tasks in javscript . but if you intend to write complex logic like you declare then you can't continue using that same one line code style .



AngularJS is still the hot

AngularJS is still the hot "new" thing although it's not really new. By a coincidence, I was doing a bit of personal development on a simple html/angularjs/bootstrap3 app where I didn't want any back end and simple content injection.

I was trying to figure out how to create dynamic HTML without having to write a butt load of javascript to do it.

In the end I chose to use showdown/bt-markdown to inject content, and wrote the equivalent of theme_link to return either a link in markdown or a h3, if no href present. That way I didn't have to use the dreaded "unsafe" directive.

It seemed to me like I was trading off "blobs" in my content for "blobs" in my partials as partials just seem to end up looking like the output of WYSIWYG editors or nasty templates. I think as I keep learning Angular I might have to just write the equivalent of Views or something to keep my partials as simple and re-usable as possible.



Partials and templating

One of the interesting advances that's coming in Drupal 8 is the use of the Twig templating system for Drupal themes. There's an implementation of Twig in JS in addition to PHP -- I'm curious whether that could lead to a world where rendering a chunk of content would use the same templates on the client AND the server side.




I'm curious why you chose to write this by adding a JS framework to Drupal rather than making a AJAX call to render it?



Why not #theme

In your block content you used #markup = theme(..). Isn't it better to do something like #theme = '..' ? Then another module could do a block_view_alter() before HTML is rendered.




I have just updated the full example and related snippet with your suggestion.





I am unconvinced that the amount or complexity of equivalent jQuery code for this feature would be sufficient to warrant adding Angular to the mix. I suspect that a much better example could have been presented to make the case.



Added a jQuery example

I have just added a link to a jQuery example in the article. You can find it at

The main problem I find with this jQuery implementation is the lack of separation between logic and markup. This makes the code more verbose; having to define longer ids for each form element and then using long selectors to set or obtain their values.

AngularJS also takes care of logging errors (console.log() may not be available in some browsers). In JQuery, using JSONP, if the request fails, you seem to have to chance to catch the error (or at least I was not able to while writing the example).



Angular vs Backbone

I've used angular myself for simplifying javascript functionality in Drupal projects. I just learned though that Drupal 8 will be shipping with Backbone. It makes me wonder if we should start getting used to the incumbent Backbone instead of the edgy Angular. What are your thoughts? Could they conflict?


David Corbacho

Great article!

Great article again Juampy,

The main idea of the article is how useful can be to decouple dynamic data from Drupal rendering.. so we can take advantage of Cache, and in the other hand, the power of libraries like AngularJS

The example is just that, an example. Probably is overkill to use a full framework for such a simple form. But in the moment you start to add more data, UI dependencies, events, etc, you will appreciate to have a JS framework helping you.

To complete the article I created jsfiddles with your examples, and a Backbone.js one, for comparison:






Thanks for gathering those up

Thanks for gathering those up David! I totally agree with you that this article is just an example to encourage people to consider a different approach.

Just a note: AngularJS has a very small footprint and that has let us use it on projects along with many other libraries without any issues.


Add Your Comment