angularjsfrontendngroute

When clicking very quickly on Angularjs app page doesn't load


FYI - I am very new to Angular...not my code mostly from tutorial on Lynda which I am playing with. I noticed when I am doing a type of "pagination" where I am showing different elements from a data.json file, the page doesn't load if I click page back anchor links too quickly to show the next or previous item. The culprit begins somewhere as a result of the anchor tags here (details.html file) / in the controller of details. I am wondering if it's async/await not being used issue.

<div class="container">
    <div class="row">
      <div class="col-12 mt-3">
          <div class="card">
            <div class="card-header d-flex align-items-start justify-content-between">
              <h1 class="card-title my-0">{{artists[whichItem].name}}</h1>
              <nav class="btn-group">
                <a class="btn btn-sm btn-secondary" 
                  href="#/details/{{prevItem}}">&lt;</a>
                <a class="btn btn-sm btn-secondary" 
                  href="#/">&bull;Home</a>
                <a class="btn btn-sm btn-secondary" 
                  href="#/details/{{nextItem}}">&gt;</a>
              </nav>
            </div>
            <div class="card-body"
              ng-model="artists">
              <h4 class="card-title text-dark mt-0">{{artists[whichItem].reknown}}</h4>
              <img class="float-left mr-2 rounded"
                ng-src="images/{{artists[whichItem].shortname}}_tn.jpg"
                alt="Photo of {{artists[whichItem].name}}">
              <div class="card-text text-secondary">{{artists[whichItem].bio}}</div>
            </div>
          </div>
      </div>
    </div>
  </div>

In the meantime - By searching different things online I added a

.otherwise({
  redirectTo: '/'
});

a redirect so something shows up. It'd be great if someone can please help explain what's causing that and how to fix it. I am posting the code below. I also added console.logs to help me debug in my controller, but I was not successful.

My smaller controller - (controllers.js):

var myControllers = angular.module('myControllers', []);

myControllers.controller('SearchController', function MyController($scope, $http) {
    $scope.sortArtistBy = 'name';
    $http.get('js/data.json').then(
      (response) => $scope.artists = response.data
    );
}); 

myControllers.controller('DetailsController', function MyController($scope, $http, $routeParams) {
  $http.get('js/data.json').then(
    function(response) {
      $scope.artists = response.data
      $scope.whichItem = $routeParams.itemId;

      if($routeParams.itemId > 0){
        $scope.prevItem = Number($routeParams.itemId) - 1;
        console.log("I am going to 18")
      } else {
        console.log("I am going to 20")
        $scope.prevItem = $scope.artists.length - 1;
      }

      if($routeParams.itemId < $scope.artists.length - 1){
        console.log("I am going to 25")
        $scope.nextItem = Number($routeParams.itemId) + 1;
      } else {
        console.log("I am going to 28")
        $scope.nextItem = 0;
      }
    }
  );
}); 

My main app controller (app.js):

var myApp = angular.module('myApp', [
  'ngRoute',
  'myControllers'
]);

myApp.config(['$routeProvider', function($routeProvider) {
  $routeProvider
    .when('/', {
      templateUrl: 'js/partials/search.html',
      controller: 'SearchController'
    })
    .when('/details/:itemId', {
      templateUrl: 'js/partials/details.html',
      controller: 'DetailsController'
    })
    .otherwise({
      redirectTo: '/'
    });
}]);

My (index.html) file:

<!DOCTYPE html>
<html ng-app="myApp">
<head>
  <meta charset="utf-8">
  <title>AngularJS</title>
  <meta name="viewport" content="width=device-width">

  <link rel="stylesheet" href="lib/bootstrap/bootstrap.min.css">
  <link rel="stylesheet" href="css/style.css">

  <script src="lib/angular/angular.min.js"></script>
  <script src="lib/angular/angular-route.min.js"></script>

  <script src="js/app.js"></script>
  <script src="js/controllers.js"></script>
</head>
<body class="bg-secondary">

<div ng-view></div>


<script src="lib/jquery/jquery.min.js"></script>
<script src="lib/bootstrap/popper.min.js"></script>
<script src="lib/bootstrap/bootstrap.min.js"></script>

</body>
</html>

Solution

  • One approach is to cache the data in a service:

    app.service("dataService", function($http) {
        var cache;
        this.get = () => {
            cache = cache || $http.get('js/data.json');
            return cache;
        };
    })
    

    Then in the controller:

    app.controller('DetailsController', function MyController($scope, dataService, $routeParams) {
      dataService().then(
        function(response) {
          $scope.artists = response.data
          $scope.whichItem = $routeParams.itemId;
          //...
        }
      );
    });
    

    By caching the $http promise, the app avoids repeating identical requests to the server.