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

1

0

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?

Gemmagemmate answered 18/2, 2016 at 20:58 Comment(0)
U
1

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.

Ultramarine answered 19/2, 2016 at 13:55 Comment(2)
I am marking this as accepted because it works on my devbox. I notice that I can click anywhere on the web page to restart the timer, even other areas of a page (like the TOC) that are not in the < section > tag bound to DemoCtrl. Is this because angular-idle.js controls the entire browser window and not just the section bound to DemoCtrl? I am also curious if I add other controllers to other html elements in index.html if clicking on the html elements controlled by other controllers will also restart the ngIdle timer? Thank you in advance for clarifying this.Gemmagemmate
@Gemmagemmate That's correct. At this time, ng-idle waits for interrupt events on the whole document to bubble up; it does not handle per-element detection. That's out of scope of the intention of ng-idle, but I suppose a fork could be made to support this using directives. As an aside, the port I made of this for Angular 2 can be used to detect activity on anything you want. That doesn't help you in Angular 1 apps, but I might rewrite ng-idle for Angular 1 to support a similar model.Ultramarine

© 2022 - 2024 — McMap. All rights reserved.