在AngularJS的视图之间切换时维护范围的模型

我正在学习AngularJS。 比方说我有/ view1使用My1Ctrl/ view2使用My2Ctrl ; 可以导航到使用选项卡,其中每个视图有自己的简单,但不同的forms。

如何确保以view1的formsinput的值不会重置,当用户离开,然后返回到view1

我的意思是,第二次访问如何保持与我离开模型完全相同的状态?

我花了一些时间来研究这样做的最佳方式。 我也想保持状态,当用户离开页面,然后按下后退button,返回到旧页面; 而不仅仅是把我所有的数据都放到根目录

最终的结果是为每个控制器 提供服务 。 在控制器中,如果清除了函数和variables,则不需要关心它们。

控制器的服务是通过dependency injection来注入的。 由于服务是单例,它们的数据不会像控制器中的数据一样被销毁。

在服务中,我有一个模型。 该模型只有数据 – 没有function – 。 这样它可以从JSON来回转换来坚持下去。 我使用html5 localstorage进行持久化。

最后我用window.onbeforeunload$rootScope.$broadcast('saveState'); 让所有的服务知道他们应该保存他们的状态,并且$rootScope.$broadcast('restoreState')让他们知道恢复他们的状态(用于当用户离开页面并按回退键返回到页面)。

为我的userController调用userService的示例服务:

 app.factory('userService', ['$rootScope', function ($rootScope) { var service = { model: { name: '', email: '' }, SaveState: function () { sessionStorage.userService = angular.toJson(service.model); }, RestoreState: function () { service.model = angular.fromJson(sessionStorage.userService); } } $rootScope.$on("savestate", service.SaveState); $rootScope.$on("restorestate", service.RestoreState); return service; }]); 

userController的例子

 function userCtrl($scope, userService) { $scope.user = userService; } 

该视图然后使用这样的绑定

 <h1>{{user.model.name}}</h1> 

应用程序模块中 ,在运行函数中,我处理saveStaterestoreState广播

 $rootScope.$on("$routeChangeStart", function (event, next, current) { if (sessionStorage.restorestate == "true") { $rootScope.$broadcast('restorestate'); //let everything know we need to restore state sessionStorage.restorestate = false; } }); //let everthing know that we need to save state now. window.onbeforeunload = function (event) { $rootScope.$broadcast('savestate'); }; 

正如我所提到的,这一段时间来到这一点。 这是一个非常干净的做法,但是在Angular开发时,做一些我认为是非常普遍的事情,这是相当不错的工程。

我希望看到更容易,但作为干净的方式来处理控制器之间的状态,包括当用户离开和返回到页面。

有点迟到的答案,但只是更新小提琴最佳做法

的jsfiddle

 var myApp = angular.module('myApp',[]); myApp.factory('UserService', function() { var userService = {}; userService.name = "HI Atul"; userService.ChangeName = function (value) { userService.name = value; }; return userService; }); function MyCtrl($scope, UserService) { $scope.name = UserService.name; $scope.updatedname=""; $scope.changeName=function(data){ $scope.updateServiceName(data); } $scope.updateServiceName = function(name){ UserService.ChangeName(name); $scope.name = UserService.name; } } 

$ rootScope是一个很大的全局variables,对于一次性事物或者小应用程序来说是很好的select。 如果要封装模型和/或行为(可能在别处重复使用),请使用服务。 除了提到的OP之后的谷歌小组,另请参阅https://groups.google.com/d/topic/angular/eegk_lB6kVs/discussion

Angular并没有真正提供你正在寻找的开箱即用function。 我会做什么来完成你以后使用下面的附加

UI路由器和UI路由器附加function

这两个将为您提供基于状态的路由和粘滞状态,您可以在状态之间选项卡,所有信息将被保存为范围“保持活着”可以这么说。

检查这两个文件,因为它非常简单,UI路由器额外也有一个很好的演示粘性状态的工作。

我有同样的问题,这是我做了什么:我有一个在同一页面(没有Ajax)有多个视图的SPA,所以这是模块的代码:

 var app = angular.module('otisApp', ['chieffancypants.loadingBar', 'ngRoute']); app.config(['$routeProvider', function($routeProvider){ $routeProvider.when('/:page', { templateUrl: function(page){return page.page + '.html';}, controller:'otisCtrl' }) .otherwise({redirectTo:'/otis'}); }]); 

我只有一个控制器的所有意见,但问题是一样的问题,控制器总是刷新数据,为了避免这种行为,我做了上面的人build议,我创build了一个服务,为此目的,然后通过它给控制器如下:

 app.factory('otisService', function($http){ var service = { answers:[], ... } return service; }); app.controller('otisCtrl', ['$scope', '$window', 'otisService', '$routeParams', function($scope, $window, otisService, $routeParams){ $scope.message = "Hello from page: " + $routeParams.page; $scope.update = function(answer){ otisService.answers.push(answers); }; ... }]); 

现在我可以从我的任何视图调用更新函数,传递值和更新我的模型,我没有必要使用HTML5 apis的持久性数据(这是在我的情况下,也许在其他情况下,将需要使用HTML5 apis像localstorage和其他的东西)。

解决scheme,将在这些范围内的多个作用域和多个variables

这个服务基于Anton的答案,但是更具扩展性,可以在多个范围内工作,并允许在同一范围内select多个范围variables。 它使用pathpath索引每个作用域,然后作用域variables名称索引更深一层。

使用此代码创build服务:

 angular.module('restoreScope', []).factory('restoreScope', ['$rootScope', '$route', function ($rootScope, $route) { var getOrRegisterScopeVariable = function (scope, name, defaultValue, storedScope) { if (storedScope[name] == null) { storedScope[name] = defaultValue; } scope[name] = storedScope[name]; } var service = { GetOrRegisterScopeVariables: function (names, defaultValues) { var scope = $route.current.locals.$scope; var storedBaseScope = angular.fromJson(sessionStorage.restoreScope); if (storedBaseScope == null) { storedBaseScope = {}; } // stored scope is indexed by route name var storedScope = storedBaseScope[$route.current.$$route.originalPath]; if (storedScope == null) { storedScope = {}; } if (typeof names === "string") { getOrRegisterScopeVariable(scope, names, defaultValues, storedScope); } else if (Array.isArray(names)) { angular.forEach(names, function (name, i) { getOrRegisterScopeVariable(scope, name, defaultValues[i], storedScope); }); } else { console.error("First argument to GetOrRegisterScopeVariables is not a string or array"); } // save stored scope back off storedBaseScope[$route.current.$$route.originalPath] = storedScope; sessionStorage.restoreScope = angular.toJson(storedBaseScope); }, SaveState: function () { // get current scope var scope = $route.current.locals.$scope; var storedBaseScope = angular.fromJson(sessionStorage.restoreScope); // save off scope based on registered indexes angular.forEach(storedBaseScope[$route.current.$$route.originalPath], function (item, i) { storedBaseScope[$route.current.$$route.originalPath][i] = scope[i]; }); sessionStorage.restoreScope = angular.toJson(storedBaseScope); } } $rootScope.$on("savestate", service.SaveState); return service; }]); 

将此代码添加到您的应用程序模块中的运行function:

 $rootScope.$on('$locationChangeStart', function (event, next, current) { $rootScope.$broadcast('savestate'); }); window.onbeforeunload = function (event) { $rootScope.$broadcast('savestate'); }; 

将restoreScope服务注入您的控制器(下面的示例):

 function My1Ctrl($scope, restoreScope) { restoreScope.GetOrRegisterScopeVariables([ // scope variable name(s) 'user', 'anotherUser' ],[ // default value(s) { name: 'user name', email: 'user@website.com' }, { name: 'another user name', email: 'anotherUser@website.com' } ]); } 

上面的例子将初始化$ scope.user到存储的值,否则默认为提供的值并保存。 如果closures页面,刷新页面或更改路由,则所有已注册的作用域variables的当前值将被保存,并在下一次访问路由/页面时恢复。

服务的另一种select是使用价值存储。

在我的应用程序的基础上,我添加了这个

 var agentApp = angular.module('rbAgent', ['ui.router', 'rbApp.tryGoal', 'rbApp.tryGoal.service', 'ui.bootstrap']); agentApp.value('agentMemory', { contextId: '', sessionId: '' } ); ... 

然后在我的控制器中,我只是参考价值商店。 如果用户closures浏览器,我认为它不成立。

 angular.module('rbAgent') .controller('AgentGoalListController', ['agentMemory', '$scope', '$rootScope', 'config', '$state', function(agentMemory, $scope, $rootScope, config, $state){ $scope.config = config; $scope.contextId = agentMemory.contextId; ...