简体   繁体   中英

How can I get multiple Angular JS routes to share a single controller instance?

I have an angular JS app which has an intro page and a 'working' page.. A simplified version of my html looks like:

 (function () { 'use strict'; var MyController = function (_, $rootScope, $scope, $location, $anchorScroll, $timeout, gettextCatalog, service) { var self = this; console.log("test"); //More code which invokes http requests }; angular.module('my.controller', [ 'gettext', 'lodash', 'ngRoute', 'ngSanitize', 'ngAnimate', 'my.service' ]).config( function ($routeProvider) { $routeProvider.when('/', { 'templateUrl': 'modules/home.html', 'reloadOnSearch': false }).when('/chatting', { 'templateUrl': 'modules/working.html', 'reloadOnSearch': false }); }).controller('MyController', MyController); }()); 
 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script> <html id="ng-app" ng-app="app" ng-controller="MyController as myCtrl"> <head> <link rel="stylesheet" href="styles/main.css"> <title>What's in Theaters</title> </head> <body id="app-body" class="dialog-body"> <div style="height: 100%; width: 100%" ng-view></div> <script src="bower_components/angular/angular.js"></script> <script src="bower_components/angular-gettext/dist/angular-gettext.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-animate/angular-animate.js"></script> <script src="app.js"></script> <script src="modules/my-controller.js"></script> </body> </html> 

The problem I have is that when I move from one route to another ie from "/" to "/#working" the MyController is re-initialized and the http requests which were already completed are now discarded.. How do I share the same instance of the controller across both routes?

Each view bound to a controller creates it's own instance of that controller. Controller's are only shared by view inheritance, that is, a child view will have access to the same instance of the parent's controller.

However that doesn't seem to be what you are trying to do. It sounds like what you want to do is persist the state of some data (acquired via http requests) between controller instances. In that case, what you'd likely want to do is move the request logic into a service (or factory) and then inject that service into the controller. Since services are singletons in angular, your requests should now only be performed once.

Example:

var MyController = function (_, $rootScope, $scope, $location, $anchorScroll, $timeout, gettextCatalog, service, yourHttpService) {
        var self = this;
        console.log("test");

// get data from your http service here... perhaps $scope.data = yourHttpService.getData(...).then(...);
    };


.factory('yourHttpService', function($http, $q) {

    var dataCache = ...; // create a local memory db to store the data

    return {
       getData: function(...) {
          var deferred = $q.defer();

          // check to see if the data is already cached, if so resolve the promise with the cached data

          // if data is not cached, perform the $http request to fetch the data, then cache it and resolve your promise

          return deferred.promise;
       };
    };

});

You can always pass your controller while defining your routes

$routeProvider.when('/', {
                    'templateUrl': 'modules/home.html',
                    'controller' : MyController,
                    'reloadOnSearch': false

                }).when('/chatting', {
                    'templateUrl': 'modules/working.html',
                    'controller' : MyController,
                    'reloadOnSearch': false
                });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM