Angular ui-router and Bootswatch

Note: This is the continuation of Setup Yeoman and Angular. We're building the WooApp front-end in Angular right now.

ui-router and Bootswatch

Why ui-router?

In the Yeoman Angular Generator, you can select Angular components and in the previous Setup Yeoman and Angular tutorial, we just finished the default config. This means angular-route was installed. The AngularJS router modules are nice and does the job of routing but we will want more for routing. We'll be adding roles, permissions, and state management in future tutorials.

I really like this explanation from someone in the stackoverflow community.

In essence, ui-router is ngRouter with more features, under the sheets it is quite different. These additional features are very useful for larger applications. - Wilgert & TheSharpieOne via stackoverflow

Another good explanation: UI-Router: Why many developers don’t use AngularJS’s built-in router.

HA! There are so many great developer resources out there! Woo!

Installation of ui-router

Let's first discover what we'll be changing in the app. Oh! Also, I use Sublime Text as my code editor.

Let's look at bower.json in the root of the folder.

{
  "name": "wooapp",
  "version": "0.0.0",
  "dependencies": {
    "angular": "^1.4.0",
    "bootstrap-sass-official": "^3.2.0",
    "angular-animate": "^1.4.0",
    "angular-cookies": "^1.4.0",
    "angular-resource": "^1.4.0",
    "angular-route": "^1.4.0",
    "angular-sanitize": "^1.4.0",
    "angular-touch": "^1.4.0"
  },
  "devDependencies": {
    "angular-mocks": "^1.4.0"
  },
  "appPath": "app",
  "moduleName": "wooappApp",
  "overrides": {
    "bootstrap": {
      "main": [
        "less/bootstrap.less",
        "dist/css/bootstrap.css",
        "dist/js/bootstrap.js"
      ]
    }
  }
}

You see on line 10 that angular-route is installed. Cool. Let's uninstall it!

bower uninstall angular-route --save

Checkout bower.json again. It should have updated and the angular-route should be gone.

Now, let's go to /app/scripts/app.js. This is where the module wooappApp is named and dependencies are listed. Right under the .module(...) is the .config(...) that holds all the routing information.

'use strict';

/**
 * @ngdoc overview
 * @name wooappApp
 * @description
 * # wooappApp
 *
 * Main module of the application.
 */
angular
  .module('wooappApp', [
    'ngAnimate',
    'ngCookies',
    'ngResource',
    'ngRoute',
    'ngSanitize',
    'ngTouch'
  ])
  .config(function ($routeProvider) {
    $routeProvider
      .when('/', {
        templateUrl: 'views/main.html',
        controller: 'MainCtrl',
        controllerAs: 'main'
      })
      .when('/about', {
        templateUrl: 'views/about.html',
        controller: 'AboutCtrl',
        controllerAs: 'about'
      })
      .otherwise({
        redirectTo: '/'
      });
  });

In the .module(...), let's remove the 'ngRoute' dependency. Also, remove the '$routeProvider' provider module from .config(function ($routeProvider)..).

Now, let's comment out the $routeProvider.when....otherwise...;. I'll want to comment this code because the view routes and controllers are already there and I just need to copy and paste them in the new code.

The new app.js should look like this:

'use strict';

/**
 * @ngdoc overview
 * @name wooappApp
 * @description
 * # wooappApp
 *
 * Main module of the application.
 */
angular
  .module('wooappApp', [
    'ngAnimate',
    'ngCookies',
    'ngResource',
    'ngSanitize',
    'ngTouch'
  ])
  .config(function () {
    // $routeProvider
    //   .when('/', {
    //     templateUrl: 'views/main.html',
    //     controller: 'MainCtrl',
    //     controllerAs: 'main'
    //   })
    //   .when('/about', {
    //     templateUrl: 'views/about.html',
    //     controller: 'AboutCtrl',
    //     controllerAs: 'about'
    //   })
    //   .otherwise({
    //     redirectTo: '/'
    //   });
  });

Now let's install ui-router!

bower install angular-ui-router --save

The --save is important because we want to save it to the bower.json so we can install it on other environments.

You should now see angular-ui-router in the bower.json. Neat!

Now, let's go back to the /app/scripts/app.js and add ui.router dependency in the .module(...).

Let's update the .config(...) with the ui-router code. Add in $stateProvider and $urlRouterProvider and now we wire it up with states.

We need a fallback if a state doesn't exist, so we'll make home our fallback state with $urlRouterProvider.otherwise("/").

Time to add in the states via the $stateProvider

$stateProvider
  .state('home', {
    url: '/',
    templateUrl: 'views/main.html',
    controller: 'MainCtrl',
  })
  .state('about', {
    url: '/about',
    templateUrl: 'views/about.html',
    controller: 'AboutCtrl',
  });

Looks very similar to the $routeProvider that we commented out. All we needed to do was just transfer over the templateURLs and Controllers.

We can delete the commented code now and here's what app.js should look like:

'use strict';

/**
 * @ngdoc overview
 * @name wooappApp
 * @description
 * # wooappApp
 *
 * Main module of the application.
 */
angular
  .module('wooappApp', [
    'ui.router',
    'ngAnimate',
    'ngCookies',
    'ngResource',
    'ngSanitize',
    'ngTouch'
  ])
  .config(function ($stateProvider, $urlRouterProvider) {

    $urlRouterProvider.otherwise("/");

    $stateProvider
      .state('home', {
        url: '/',
        templateUrl: 'views/main.html',
        controller: 'MainCtrl',
      })
      .state('about', {
        url: '/about',
        templateUrl: 'views/about.html',
        controller: 'AboutCtrl',
      });
  });

One last thing to do! Go to the /app/index.html and on line 51 you will swap out <div ng-view=""></div> for <div ui-view></div>. I won't show this html, but you can look on the repo for it.

Awesome! Let's start up the app.

grunt serve

Now you're using state to serve up the views. Party time!!!

Update UI with Bootswatch

Let's quickly update the Bootstrap theme to something new. This will be nice to have for future building.

I like to use Bootswatch because they have cool themes and have a few things ready out of the box.

Let's install the Superhero theme. Let's go back to the Bootswatch homepage and download the _variables.scss and the _bootswatch.scss. In this case, you can download or copy/paste into the editor. You'll want to put them next to main.scss in the /app/styles. You can see here in the Github repo.

In the main.scss you can add the variables on the second line after the $icon-font-path: "../bower_components/bootstrap-sass-official/assets/fonts/bootstrap/"; with @import "_variables.scss"; and then add @import "_bootswatch.scss"; after @import "bootstrap-sass-official/assets/stylesheets/_bootstrap.scss";.

This is what main.scss should look like:

$icon-font-path: "../bower_components/bootstrap-sass-official/assets/fonts/bootstrap/";
@import "_variables.scss";

// bower:scss
@import "bootstrap-sass-official/assets/stylesheets/_bootstrap.scss";
// endbower

@import "_bootswatch.scss";
...

Start up the app with grunt serve and boom! NEW LOOK!

Bootswatch Superman

Why did we just do this? Well, if you look at the _bootswatch.scss and _variables.scss, you can see that this will be pretty powerful in the future for styling. The _variables.scss can update your font, colors... etc. through the SASS vaiables like $gray-base. Awesome, right? And _bootswatch.scss is a great start to making an awesome theme yourself.

Checkout the Repo for the code.