Install and use Angular UI Bootstrap components

Note: This is the continuation of Angular App build tutorial. We're building the WooApp front-end in Angular right now.

Angular UI Bootstrap

We're going to install and integrate some simple directives from Angular UI Bootstrap. These directives are reusable and keeps the controllers and UI clean and organized. Pretty simple to integrate!

Installation

Let's bower install it.

bower install angular-bootstrap --save

Next, add it to the dependency ui.bootstrap to /app/scripts/app.js like so.

angular
  .module('wooappApp', [
    'ui.router',
    'ngAnimate',
    'ngCookies',
    'ngResource',
    'ngSanitize',
    'ngTouch',
    'ui.bootstrap'
  ])

Now, let's add a modal! Go ahead and start the server with grunt serve. The app should load in the browser automatically with http://localhost:9000. Here's the documentation for the modal.

Add a new folder called modal into the /app/views directory and then add a new html document called example.html. Copy and past the example template there in the example.html.

<div class="modal-header">
  <h3 class="modal-title">I'm a modal!</h3>
</div>
<div class="modal-body">
  <ul>
    <li ng-repeat="item in items">
      <a href="#" ng-click="$event.preventDefault(); selected.item = item">{{ item }}</a>
    </li>
  </ul>
    Selected: <b>{{ selected.item }}</b>
</div>
<div class="modal-footer">
  <button class="btn btn-primary" type="button" ng-click="ok()">OK</button>
  <button class="btn btn-warning" type="button" ng-click="cancel()">Cancel</button>
</div>

Excellent! You just made a template for a modal!

Next, replace ng-href="#/" with ng-click="open()" on the green Splendid! button in the main.html template on line 7.

...
<p><a class="btn btn-lg btn-success" ng-click="open()">Splendid!<span class="glyphicon glyphicon-ok"></span></a></p>
...

Let's add the selected scope variable to the bottom of the marketing div. This will show us the cool scoping possible from the modal.

<div class="row marketing">
  ...
  <div ng-show="selected">Selection from a modal: {{ selected }}</div>
</div>

Last, let's add the functionality in the controller. Open main.js in /app/scripts/controllers. Add $scope, $uibModal, $log services to the MainCtrl controller.

.controller('MainCtrl', function ($scope, $uibModal, $log)

Copy and paste everything from the example into the MainCtrl controller and then change the templateUrl: 'myModalContent.html', to the location of our example.html template to templateUrl: 'views/modal/example.html'.

angular.module('wooappApp')
  .controller('MainCtrl', function ($scope, $uibModal, $log) {
    this.awesomeThings = [
      'HTML5 Boilerplate',
      'AngularJS',
      'Karma'
    ];

    $scope.items = ['item1', 'item2', 'item3'];

    $scope.animationsEnabled = true;

    $scope.open = function (size) {

        var modalInstance = $uibModal.open({
          animation: $scope.animationsEnabled,
          templateUrl: 'views/modal/example.html',
          controller: 'ModalInstanceCtrl',
          size: size,
          resolve: {
            items: function () {
              return $scope.items;
            }
          }
        });

        modalInstance.result.then(function (selectedItem) {
          $scope.selected = selectedItem;
        }, function () {
          $log.info('Modal dismissed at: ' + new Date());
        });
    };

    $scope.toggleAnimation = function () {
        $scope.animationsEnabled = !$scope.animationsEnabled;
    };
  });

Time to add a new controller called ModalInstanceCtrl as seen in the example. Just take all of the code from the example and throw it on the end of the controller like so.

'use strict';

/**
 * @ngdoc function
 * @name wooappApp.controller:MainCtrl
 * @description
 * # MainCtrl
 * Controller of the wooappApp
 */
angular.module('wooappApp')
  .controller('MainCtrl', function ($scope, $uibModal, $log) {
    this.awesomeThings = [
      'HTML5 Boilerplate',
      'AngularJS',
      'Karma'
    ];

    $scope.items = ['item1', 'item2', 'item3'];

    $scope.animationsEnabled = true;

    $scope.open = function (size) {

        var modalInstance = $uibModal.open({
          animation: $scope.animationsEnabled,
          templateUrl: 'views/modal/example.html',
          controller: 'ModalInstanceCtrl',
          size: size,
          resolve: {
            items: function () {
              return $scope.items;
            }
          }
        });

        modalInstance.result.then(function (selectedItem) {
          $scope.selected = selectedItem;
        }, function () {
          $log.info('Modal dismissed at: ' + new Date());
        });
    };

    $scope.toggleAnimation = function () {
        $scope.animationsEnabled = !$scope.animationsEnabled;
    };
  })
  .controller('ModalInstanceCtrl', function ($scope, $uibModalInstance, items) {

      $scope.items = items;
      $scope.selected = {
        item: $scope.items[0]
      };

      $scope.ok = function () {
        $uibModalInstance.close($scope.selected.item);
      };

      $scope.cancel = function () {
        $uibModalInstance.dismiss('cancel');
      };
    });

The ModalInstanceCtrl controller will be called when the modal is initiated in the $scope.open = function(... controller: 'ModalInstanceCtrl',..) in MainCtrl. This is just an example of what you can do quickly. If this were a modal used in multiple areas of the app, then we would be a bit more organized in the code and use the Yeoman method of generating a controller like yo angular:controller ModalInstanceCtrl. This would create a new controller that we would then use in the modal function.

Now test it! The app should have refreshed and click the green Splendid! button. You should see the modal popup. Select "item2" by clicking on it in the list and see the scope change in the modal area to Selected: item2. In the modal template the code that responses to that is Selected: <b>{{ selected.item }}</b>.

Modal Example 1

Click the "ok" button. The modal will disappear and then at the bottom of the page where we added the html snippet in the marketing div should show Selection from a modal: item2. That scope was pass from the modal to the view.

Modal Example 2

If you open up your developer tools in the browser and then click the "cancel" button in the modal, you can see in the console tab that the dismissal was recorded too.

The dismissal and success result is from the code in the MainCtrl controller $scope.open = function (size)... code.

modalInstance.result.then(function (selectedItem) {
      $scope.selected = selectedItem;
    }, function () {
      $log.info('Modal dismissed at: ' + new Date());
});

The "ok" button pressed in the modal is scoped in the ModalInstanceCtrl controller.

$scope.ok = function () {
 $uibModalInstance.close($scope.selected.item);
};

The "cancel" button scoped in the same controller.

$scope.cancel = function () {
 $uibModalInstance.dismiss('cancel');
};

Now you can see how awesome these directives can be! Look through the documentation and see if you can add more actions and functions to the app via their documentation. We'll be getting deeper with these directives when we build out the app more.

Checkout the Repo for the code for a full example of what we did!