Constructing a Dashboard with AngularJS

Originally published on the Back& blog.

What is a Dashboard

A dashboard consists of a toolbar and a collection of panels presenting information in tables, charts, and grids. Making different selections, and entering filtering values at the toolbar, such as selecting date ranges, causes the content of the panels to change. AngularJS has a collection of features that facilitate a streamlined construction of a dashboard.

Structure a Dashboard in AngularJS

We structure the dashboard as a collection of controllers: a controller for the toolbar, and a separate controller for each panel. Constants are concentrated in a constants service constantsService. The selection and filtering state of the toolbar, is maintained in a filter service filterService.

Once a selection is made in the toolbar, it is broadcast to the other controllers, which make the required adjustments. This may include filterign of data, redrawing of visualizations, or fetching of data from the server according to the selection.

Single Page Application Structure

The app is a single page application (SPA) constructed using Bootstrap.

Include Bootstrap and AngularJS:

The page body:

Include the js files:

It is powered by app.js in the standard AngularJS way:

'use strict';

var myApp = angular.module('myApp', [
  'myApp.filters',
  'myApp.services',
  'myApp.directives',
  'myApp.controllers'
]);

The page is structured as a navigation bar for the toolbar and a sequence of rows for the panels.

The toolbar is a navigation bar controlled by the toolbarCtrl controller. It has a drop down for each possible selection or filter. Below we show a selection of a market, and a selection of a time period.

The ranges for selections are set in the selectionScape variable of the toolbar controller:

app.controller("toolbarCtrl", function($scope, $rootScope, $http, $filter) {

  $scope.selectionScape = {
    markets: [ "NYSE", "NASDAQ", "DAX", "CAC" ],
    periods: [ "1D", "1M", "1Q", "1Y", "5Y", "YTD" ]
  };

});

The current state of selection/filtering is kept in the variable selectionState.

$scope.selectionState = {
  market: ...,
  period: ...,
  ...
}

Each panel is a row controlled by its own controller, such as the revenueCtrl, below:

App Bootstrap

When the app is started it broadcasts to all controllers to fetch the initial content of their panels.

myApp.run(function($rootScope, $timeout){
  $timeout(function() {
    $rootScope.$broadcast("setup");
  }, 1500);
});

We need the timeout in order to wait for the controllers to be created first.

Initial setup is done on receiving the setup signal from the app bootstrap:

$scope.$on('setup', function(evt){
  // fetch filtering and selection state from filterService
  // fetch data from server
});

Propagation of Filtering and Selection

The filtering and selection done at the toolbar is propagated from the toolbar via a broadcast to the other controllers. So for each possible selection operation on the toolbar, we define a function,

$scope.marketSelected = function(market){
  $scope.selectionState.market = market;
  // update the global filtering state
  filterService.setSettings('market', market);
  // broadcast the selection
  $rootScope.$broadcast("selectionChange");
};

The filtering is updated in the filter service so that all controllers can fetch it. We the selection state in the global filter service so that all controllers can use it.

Panel Content Update

Each panel controller upon receiving the selectionChange signal from the toolbar updates its state, possibly involving a fetch of data from the server:

app.controller("revenueCtrl", function($scope, filterService) {
  $scope.$on('selectionChange', function(evt){
    var period = filterService.getSettings('period');
    // get the data for the period
    $scope.fetchData(period);
  };

});

The Filter Service

The filter service stores the current filters and selections of the dashboard,

app.factory('filterService', function(){     
  // initial settings on app bootstrap
  var settings = {
    market: 'NASDAQ',
    period: '1D',
    ...
  };

  return {
    setSettings: function(property, value){
      settings[property] = value;
    },

    getSettings: function(property){
      return settings[property];
    }
  };
});

A Backend for the Dashboard

A dashboard has to fetch its data from a backend. In a subsequent post, we will show how to connect the dashboard to a backend constructed with Back&.
The connection will be through a REST API automatically constructed by Back& from a database. The dashboard will fetch its configuration, such as selection ranges from the database. Thereby making the dashboard configurable.