Why isn't this ng-idle implementation connecting modal and styling?

1.7k views Asked by At

I am trying to get ng-idle to hook up to css and modal the way it looks in this working example at this link. I have interpreted the code at the link to mean that I should type the code below to implement it, but the code below does not hook the controller or the styling up to the view. What specific changes need to be made to the code below to successfully implement ng-idle the way it looks in the demo link above, with modal warning and with styling for the buttons, etc.?

The situation can be recreated on your computer by downloading a fully functioning MINIMAL reproduction by clicking the link to this file sharing site, and then viewing the contents of index.html and app.js which are currently the following:

index.html is:

<html ng-app="demo">
  <head>
    <title title>NgIdle Sample</title> 
  </head>
  <body>

<section data-ng-controller="DemoCtrl">
{{ started }}  <!-- this SYSO of the `start` variable does not print -->
  <p>
    <button type="button" class="btn btn-success" data-ng-hide="started" data-ng-click="start()">Start Demo</button>
    <button type="button" class="btn btn-danger" data-ng-show="started" data-ng-click="stop()">Stop Demo</button>
 </p>
</section>

<script type="text/ng-template" id="warning-dialog.html">
  <div class="modal-header">
   <h3>You're Idle. Do Something!</h3>
  </div>
  <div idle-countdown="countdown" ng-init="countdown=5" class="modal-body">
   <progressbar max="5" value="5" animate="false" class="progress-striped active">You'll be logged out in {{countdown}} second(s).</progressbar>
  </div>

</script>
<script type="text/ng-template" id="timedout-dialog.html">
  <div class="modal-header">
   <h3>You've Timed Out!</h3>
  </div>
  <div class="modal-body">
   <p>
      You were idle too long. Normally you'd be logged out, but in this demo just do anything and you'll be reset.
   </p>
 </div>
</script>

    <script src="bower_components/angular/angular.js"></script>
    <script src="bower_components/ng-idle/angular-idle.min.js"></script>
    <script src="bower_components/angular-bootstrap/ui-bootstrap.min.js"></script>

    <script src="scripts/app.js"></script>
</body>
</html>

And app.js is:

'use strict';

angular.module('demo', ['ngIdle', 'ui.bootstrap'])
    .controller('DemoCtrl', function($scope, Idle, Keepalive, $modal){
      $scope.started = false;

      function closeModals() {
        if ($scope.warning) {
          $scope.warning.close();
          $scope.warning = null;
        }

        if ($scope.timedout) {
          $scope.timedout.close();
          $scope.timedout = null;
        }
      }

      $scope.$on('IdleStart', function() {
        closeModals();

        $scope.warning = $modal.open({
          templateUrl: 'warning-dialog.html',
          windowClass: 'modal-danger'
        });
      });

      $scope.$on('IdleEnd', function() {
        closeModals();
      });

      $scope.$on('IdleTimeout', function() {
        closeModals();
        $scope.timedout = $modal.open({
          templateUrl: 'timedout-dialog.html',
          windowClass: 'modal-danger'
        });
      });

      $scope.start = function() {
        closeModals();
        Idle.watch();
        $scope.started = true;
      };

      $scope.stop = function() {
        closeModals();
        Idle.unwatch();
        $scope.started = false;

      };
    })
    .config(function(IdleProvider, KeepaliveProvider) {
      IdleProvider.idle(5);
      IdleProvider.timeout(5);
      KeepaliveProvider.interval(10);
    })
 .run(['Idle', function(Idle) {
      Idle.watch();
    }]);

Now that the problem is recreated, what changes need to be made to the code above to get it to implement modal and styling as in the example/demo at the link at top of the OP?

1

There are 1 answers

2
moribvndvs On BEST ANSWER

Inside the project you TARed, there were four things:

  1. You need to make sure ng-app="demo" attribute is added to the html or body element. The value demo should be changed to match whatever you call your application when you define your application module in this line of app.js: angular.module('demo', [/* etc. */])
  2. Make sure you include ui-bootstrap-tpls.min.js and not ui-bootstrap.min.js; the latter does not include HTML templates for the directives (with the expectation that you'd supply them yourself), and the former does. See the UI-Bootstrap getting started guide.
  3. The version of UI-Bootstrap you are referencing is more recent than the version I wrote the demo with. $modal has been renamed to $uibModal, so just search and replace that token.
  4. Make sure you include Bootstrap in the CSS of your application. You started this app using a Yeoman generator, and that generator appears to compile Bootstrap SASS into CSS in styles/main.css.

Some of these things (1,2, and 4) were probably already set up for you by the Yeoman generator, and you hacked it apart trying to paste in the ng-idle demo code.

Here's your index.html (with all the commented out stuff removed):

<!doctype html>
<html>

<head>
  <meta charset="utf-8">
  <title></title>
  <meta name="description" content="">
  <meta name="viewport" content="width=device-width">
  <link rel="stylesheet" href="styles/main.css">
  <link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css" rel="stylesheet">
</head>

<body ng-app="demo">
  <!--[if lte IE 8]
  <p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p>
  [endif]//-->

  <div class="header">
    <div class="navbar navbar-default" role="navigation">
      <div class="container">
        <div class="navbar-header">

          <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#js-navbar-collapse">
            <span class="sr-only">Toggle navigation</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
          </button>

          <a class="navbar-brand" href="#/">client</a>
        </div>

        <div class="collapse navbar-collapse" id="js-navbar-collapse">

          <ul class="nav navbar-nav">
            <li class="active"><a href="#/">Home</a></li>
            <li><a ng-href="#/about">About</a></li>
            <li><a ng-href="#/">Contact</a></li>
          </ul>
        </div>
      </div>
    </div>
  </div>

  <div class="container">
    <div ng-view="">
      <section data-ng-controller="DemoCtrl">
        {{ started }}
        <!-- this SYSO of the `start` variable does not print -->
        <p>
          <button type="button" class="btn btn-success" data-ng-hide="started" data-ng-click="start()">Start Demo</button>
          <button type="button" class="btn btn-danger" data-ng-show="started" data-ng-click="stop()">Stop Demo</button>
        </p>
      </section>
    </div>
  </div>

  <div class="footer">
    <div class="container">
      <p><i class="fa fa-heart"></i> from the Yeoman team</p>
    </div>
  </div>

  <script type="text/ng-template" id="warning-dialog.html">
    <div class="modal-header">
      <h3>You&apos;re Idle. Do Something!</h3>
    </div>
    <div idle-countdown="countdown" ng-init="countdown=5" class="modal-body">
      <progressbar max="5" value="5" animate="false" class="progress-striped active">You&apos;ll be logged out in {{countdown}} second(s).</progressbar>
    </div>

  </script>
  <script type="text/ng-template" id="timedout-dialog.html">
    <div class="modal-header">
      <h3>You&apos;ve Timed Out!</h3>
    </div>
    <div class="modal-body">
      <p>
        You were idle too long. Normally you&apos;d be logged out, but in this demo just do anything and you&apos;ll be reset.
      </p>
    </div>
  </script>

  <script src="bower_components/jquery/dist/jquery.js"></script>
  <script src="bower_components/angular/angular.js"></script>
  <script src="bower_components/bootstrap-sass-official/assets/javascripts/bootstrap.js"></script>
  <script src="bower_components/angular-animate/angular-animate.js"></script>
  <script src="bower_components/angular-aria/angular-aria.js"></script>
  <script src="bower_components/angular-cookies/angular-cookies.js"></script>
  <script src="bower_components/angular-messages/angular-messages.js"></script>
  <script src="bower_components/angular-resource/angular-resource.js"></script>
  <script src="bower_components/angular-route/angular-route.js"></script>
  <script src="bower_components/angular-sanitize/angular-sanitize.js"></script>
  <script src="bower_components/angular-touch/angular-touch.js"></script>
  <script src="bower_components/ng-idle/angular-idle.min.js"></script>
  <script src="bower_components/angular-bootstrap/ui-bootstrap-tpls.min.js"></script>

  <script src="scripts/app.js"></script>
  <script src="scripts/controllers/main.js"></script>

</body>

</html>

Here's app.js:

  'use strict';
  angular.module('demo', ['ngIdle', 'ui.bootstrap'])
    .controller('DemoCtrl', function($scope, Idle, Keepalive, $uibModal){
      $scope.started = true;

      function closeModals() {
        if ($scope.warning) {
          $scope.warning.close();
          $scope.warning = null;
        }

        if ($scope.timedout) {
          $scope.timedout.close();
          $scope.timedout = null;
        }
      }

      $scope.$on('IdleStart', function() {
        closeModals();

        $scope.warning = $uibModal.open({
          templateUrl: 'warning-dialog.html',
          windowClass: 'modal-danger'
        });
      });

      $scope.$on('IdleEnd', function() {
        closeModals();
      });

      $scope.$on('IdleTimeout', function() {
        closeModals();
        $scope.timedout = $uibModal.open({
          templateUrl: 'timedout-dialog.html',
          windowClass: 'modal-danger'
        });
      });

      $scope.start = function() {
        closeModals();
        Idle.watch();
        $scope.started = true;
      };

      $scope.stop = function() {
        closeModals();
        Idle.unwatch();
        $scope.started = false;

      };
    })
    .config(function(IdleProvider, KeepaliveProvider) {
      IdleProvider.idle(5);
      IdleProvider.timeout(5);
      KeepaliveProvider.interval(10);
    })
    .run(['Idle', function(Idle) {
      Idle.watch();
    }]);

I respect a hands-on approach to learning how things work, but I'd recommend you pump the brakes a little and learn about the relationship between Angular, your yeoman generator, Bootstrap, UI-Bootstrap, and ng-idle, and how to use each of these things.