Search code examples
javascripthtmlangularjsbrowser-history

AngularJS saving dynamic content to history


I'm new to AngularJS and I'm trying to make a home page that loads dynamic content from my database to create links. When I click one of those links on the home page, it sends a request to my node server and retrieves the appropriate data from the database and displays that on the partial view. When I'm on that partial view and I click the browser's back button to go back to the home page, the dynamic content that was originally loaded doesn't display. Below is my code. Why doesn't clicking the browser's back button redisplay the home page with the dynamic content?

index.html

<!doctype html>
<html lang="en" ng-app="phonecatApp">
<head>
  <meta charset="utf-8">
  <base href="/">
  <title>My site</title>
  <link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
  <link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.css">
  <link rel="stylesheet" href="css/app.css">
  <link rel="stylesheet" href="css/animations.css">

  <script src="bower_components/jquery/jquery.js"></script>
  <script src="bower_components/angular/angular.js"></script>
  <script src="bower_components/angular-animate/angular-animate.js"></script>
  <script src="bower_components/angular-route/angular-route.js"></script>
  <script src="bower_components/angular-resource/angular-resource.js"></script>
  <script src="/js/animations.js"></script>
  <script src="/js/controllers.js"></script>
  <script src="/js/filters.js"></script>
  <script src="/js/app.js"></script>
</head>
<body ng-controller="mainController">
  <div class="container">
      <nav class="navbar navbar-default" role="navigation">
        <div class="container-fluid">
          <div class="navbar-header">
            <a class="navbar-brand" href="/" ng-click="home()">Home</a>
          </div>
          <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
            <ul class="nav navbar-nav">
            </ul>
            <form class="navbar-form navbar-left" role="search">
              <div class="form-group">
                <input type="text" class="form-control" data-provide="typeahead" autocomplete="off" placeholder="foo, bar" ng-model="query">
              </div>
            </form>
            <ul class="nav navbar-nav navbar-right">
            </ul>
          </div>
        </div>
      </nav>
  </div>
  <div class="view-container">
    <div ng-view class="view-frame"></div>
  </div>
</body>
</html>
phone-detail.html

<div class="phone-images">
  <img ng-src="{{thing.imageUrl}}"  dclass="phone">
</div>
  <h1> {{ things[0].name }} </h1>
    <iframe id="viddy" width="560" height="315" ng-src="{{  things[0].embed }}" frameborder="0" allowfullscreen autoplay="1" ></iframe>
          <p>source:</p>
          <p>{{ things[0].vid }}</p>
</div>
phone-list.html

<div class="container-fluid">
  <div class="row">
    <div class="col-md-10">
      <!--Body content-->
      <div>
        <div ng-if="things.length>1">
          <ul class="phones">
            <li ng-repeat="foo in things | filter:query"
                class="thumbnail phone-listing">
              <a href="#/{{thing.name}}" class="thumb" ng-click="search(foo.name)"><img ng-src="{{foo.imageUrl}}"></a>
              <a href="#/{{foo.name}}" ng-click="search(foo.name)">{{foo.name}}</a>
            </li>
          </ul>
        </div>
      </div>
    </div>
  </div>
</div>
//controller.js

'use strict';

/* Controllers */

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

coreControl.controller('mainController', ['$scope', '$http', '$sce', '$locationProvider'
    function($scope, $http, $sce, $locationProvider) 
    {
      //$scope.$on('$routeChangeSuccess', function(req, res) {console.log($route.current.params);})

      $scope.formData = {};
      $scope.things  = [];
      $scope.maxThings = 0;

      $http.get('/things')
        .success(function(data) 
        {
          $scope.things = data;
          $scope.maxThings = $scope.things.length;
          console.log(data);
        })
        .error(function(data) 
        {
          console.log('Error: ' + data);
        });

      $scope.home = function()
      {
        $http.get('/things')
        .success(function(data) 
        {
          $scope.things = data;
          $scope.maxThings = $scope.things.length;
          console.log(data);
        })
        .error(function(data) 
        {
          console.log('Error: ' + data);
        });
      }

      $scope.search = function(thing)
      {
        $http.get('/thing/'+thing, $scope.formData)
          .success(function(data) 
          {
            $scope.formData     = {};
            $scope.things        = data;
            $scope.msg          = "Recommend a video."
            $scope.noMatch      = false;

            if($scope.things.length == 0)
            {
              $scope.noMatch = true;
            }

            $scope.things[0].embed = $sce.trustAsResourceUrl($scope.things[0].embed+"?autoplay=0&showinfo=0&controls=0&loop=1");
            document.getElementById('viddy').src = document.getElementById('viddy').src;
            console.log(data);
          })
          .error(function(data) 
          {
            console.log('Error: ' + data);
          });
      }
    }]);
//app.js

'use strict';

var phonecatApp = angular.module('phonecatApp', [
  'ngRoute',
  'phonecatAnimations',
  'prjController'
]);

phonecatApp.config(['$routeProvider',
  function($routeProvider) {
    $routeProvider.
      when('/:thingId', {
        templateUrl: 'partials/phone-detail.html'
      }).
      otherwise({
        templateUrl: 'partials/phone-list.html'
      });
  }]);
//server.js

var express     = require('express');
var app         = express();
var mysql       = require('mysql');
var port        = process.env.PORT || 8887;
var db          = require('./config/db');
var connection  = mysql.createConnection(db);
connection.connect();

app.configure(function()
{
    app.use(express.static(__dirname + '/public'));
    app.use(express.logger('dev'));
    app.use(express.bodyParser());
});

require('./app/router')(app, connection);

app.listen(port);
exports = module.exports = app;
//router.js

module.exports = function(app, conn)
{
    app.get('*', function(req, res){
        var url = req.originalUrl;

        if(url.match(/^\/thing\/.+/))
        {
            var query_thing = url.replace(/%20/g, ' ');
            query_thing = query_thing.replace(/\/thing\//, '');
            require('./search')(query_thing, res, conn);
        }
        else
        {
            require('./populate')(res, conn);
        }
    });
};
//populate.js
module.exports = function(res, connection)
{
    function getRandIds(rep, max)
    {
        var ids = [];

        //create a list of rep-many random integers, which may have repetitions
        for (var i = 0; i < rep; i++) 
        { 
            ids.push(Math.floor(Math.random()*100) % max);
        }

        function numercalSort(a,b)
        {
            return a-b;
        }

        //sort() without the callback sorts alphabetically
        ids.sort(numercalSort);
        console.log(ids);
        var notUnique = false;

        //check that each id is unique so that the exact number of ids will be queried
        for(var i = 0; i < ids.length; i++)
        {
            if(i+1 < ids.length && ids[i] == ids[i+1]) 
            {
              notUnique = true;
            }
        }

        //recurse if the values are not all unique
        if(notUnique)
        {
            ids = getRandIds(rep, max);
        }

        return ids;
    }

    //creates a query that searches for random ids
    function queryRand(rep, max) 
    {

        var sql = "select m.name, m.imageUrl, v.vid, v.embed from things as m, videos as v where m.id=v.id and (";
        var ids = getRandIds(rep, max);

        for(var i = 0; i < ids.length; i++) 
        {
            sql += " m.id like "+ids[i];

            if(i < ids.length - 1)
            {
              sql += " or";
            }
            else
            {
              sql += ");";
            }
        }
          var sql = "select m.name, m.imageUrl, v.vid, v.embed from things as m, videos as v where m.id=v.id";
          return sql;
    }

    //handles the output
    function handleOut(err, result, fields)
    {
        if(err) throw err;
        console.log('rand results: ',result);
        res.json(result);
    }

    var repetitions = 10;    //number of things to display
    var totalCount  = 372;  // total number of things in the database
    var sql = queryRand(repetitions, totalCount);
    connection.query(sql, handleOut);
};

Solution

  • So after a long while, I finally realized that the issue was that I only had one controller that held the functionality for all my controllers. That was only loading once. Because it only loaded once, the $http.get('/things') call was only being made that once when the controller initially loaded. To resolve this, I separated out my controllers. I made one specifically for my home page, and made a separate partial for it and placed the controller specifically in that partial, so it loads every time the partial loads. This also required updating the index.html and app.js, appropriately.

    //mainController.js
    angular.module('prjController', [])
        .controller('mainController', ['$scope', '$http', '$sce',
        function($scope, $http, $sce) 
        {    
          $http.get('/things')
            .success(function(data) 
            {
              $scope.things = data;
              $scope.maxThings = $scope.things.length;
              console.log(data);
            })
            .error(function(data) 
            {
              console.log('Error: ' + data);
            });
        }]);
    
    <!-- main.html partial -->
    <div class="container-fluid" ng-controller="mainController">
          <!--Body content-->
           ...
    </div>