답변:
이 작업을 수행하는 가장 좋은 방법은 무엇입니까? 또한 사용자가 페이지를 떠난 후 뒤로 버튼을 눌러 이전 페이지로 돌아갈 때 상태를 유지하고 싶었습니다. 내 모든 데이터를 루트 스코프에 넣지 않고 .
최종 결과는 각 컨트롤러에 서비스 를 제공하는 것 입니다 입니다. 컨트롤러에는 신경 쓰지 않는 함수와 변수가 있습니다.
컨트롤러의 서비스는 의존성 주입에 의해 주입됩니다. 서비스는 싱글 톤이므로 데이터는 컨트롤러의 데이터처럼 파괴되지 않습니다.
서비스에는 모델이 있습니다. 모델에만 데이터가 있으며 기능은 없습니다. 그렇게하면 JSON에서 앞뒤로 변환하여 유지할 수 있습니다. 지속성을 위해 html5 로컬 저장소를 사용했습니다.
마지막으로 내가 사용 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>
그리고 앱 모듈 에서 실행 기능 내 에서 saveState 및 restoreState 의 브로드 캐스트 를 처리합니다.
$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에서 개발할 때 매우 일반적인 문제라고 생각하는 것을 수행하는 것은 약간의 엔지니어링입니다.
더 쉽게보고 싶지만 사용자가 페이지를 떠날 때를 포함하여 컨트롤러의 상태 유지를 처리하는 깨끗한 방법입니다.
$scope.user = userService;
당신은이 같은 있습니다 $scope.name = userService.model.name; $scope.email = userService.model.email;
. 작동하거나 뷰에서 변수를 변경해도 서비스에서 변경되지 않습니까?
답변에 약간 늦었지만 모범 사례로 업데이트 된 바이올린
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;
}
}
updateService
합니다. 컨트롤러가 파괴 될 때 호출되어야합니다. – $scope.$on('$destroy', function() { console.log('Ctrl destroyed'); $scope.updateServiceName($scope.name); });
$ rootScope는 큰 전역 변수로, 일회성 또는 소규모 앱에 적합합니다. 모델 및 / 또는 동작을 캡슐화하고 다른 곳에서 재사용하려는 경우 서비스를 사용하십시오. 언급 된 OP를 Google 그룹에 게시하는 것 외에도 https://groups.google.com/d/topic/angular/eegk_lB6kVs/discussion을 참조 하십시오 .
나는 같은 문제를 겪었다. 이것은 내가 한 일이다 : 나는 동일한 페이지에 여러 개의 뷰를 가진 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'});
}]);
모든보기에 대해 하나의 컨트롤러 만 있지만 문제는 질문과 동일합니다. 컨트롤러는 항상 데이터를 새로 고칩니다.이 동작을 피하기 위해 사람들이 위에서 제안한 것을 수행하고 해당 목적을 위해 서비스를 만든 다음 전달합니다. 다음과 같이 컨트롤러에
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 API를 사용할 필요가 없습니다 (이 경우 내 경우에는 다른 경우에는 html5를 사용해야 할 수도 있습니다) 로컬 스토리지 및 기타 자료와 같은 API).
서비스의 대안은 가치 저장소를 사용하는 것입니다.
내 앱의 기초에 이것을 추가했습니다.
var agentApp = angular.module('rbAgent', ['ui.router', 'rbApp.tryGoal', 'rbApp.tryGoal.service', 'ui.bootstrap']);
agentApp.value('agentMemory',
{
contextId: '',
sessionId: ''
}
);
...
그런 다음 컨트롤러에서 값 저장소를 참조합니다. 사용자가 브라우저를 닫으면 물건을 보유하고 있다고 생각하지 않습니다.
angular.module('rbAgent')
.controller('AgentGoalListController', ['agentMemory', '$scope', '$rootScope', 'config', '$state', function(agentMemory, $scope, $rootScope, config, $state){
$scope.config = config;
$scope.contextId = agentMemory.contextId;
...
여러 범위 및 해당 범위 내의 여러 변수에 사용할 수있는 솔루션
이 서비스는 Anton의 답변을 기반으로했지만 더 확장 가능하며 여러 범위에서 작동하며 동일한 범위에서 여러 범위 변수를 선택할 수 있습니다. 라우트 경로를 사용하여 각 범위를 인덱싱 한 다음 범위 변수 이름을 사용하여 한 수준 더 깊이 인덱싱합니다.
이 코드로 서비스를 작성하십시오.
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;
}]);
이 코드를 앱 모듈의 실행 기능에 추가하십시오.
$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를 저장된 값으로 초기화합니다. 그렇지 않으면 제공된 값으로 기본 설정되어 저장됩니다. 페이지를 닫거나 새로 고치거나 경로를 변경하면 등록 된 모든 범위 변수의 현재 값이 저장되고 다음에 경로 / 페이지를 방문 할 때 복원됩니다.
$locationChangeStart
이벤트를 사용 $rootScope
하여 서비스 에 또는 서비스에 이전 값을 저장할 수 있습니다 . 돌아 오면 이전에 저장된 모든 값을 초기화하십시오. 다음은을 사용한 빠른 데모 $rootScope
입니다.
var app = angular.module("myApp", ["ngRoute"]);
app.controller("tab1Ctrl", function($scope, $rootScope) {
if ($rootScope.savedScopes) {
for (key in $rootScope.savedScopes) {
$scope[key] = $rootScope.savedScopes[key];
}
}
$scope.$on('$locationChangeStart', function(event, next, current) {
$rootScope.savedScopes = {
name: $scope.name,
age: $scope.age
};
});
});
app.controller("tab2Ctrl", function($scope) {
$scope.language = "English";
});
app.config(function($routeProvider) {
$routeProvider
.when("/", {
template: "<h2>Tab1 content</h2>Name: <input ng-model='name'/><br/><br/>Age: <input type='number' ng-model='age' /><h4 style='color: red'>Fill the details and click on Tab2</h4>",
controller: "tab1Ctrl"
})
.when("/tab2", {
template: "<h2>Tab2 content</h2> My language: {{language}}<h4 style='color: red'>Now go back to Tab1</h4>",
controller: "tab2Ctrl"
});
});
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular-route.js"></script>
<body ng-app="myApp">
<a href="#/!">Tab1</a>
<a href="#!tab2">Tab2</a>
<div ng-view></div>
</body>
</html>
sessionStorage.restoreState
로 설정된 위치 는 표시되지 않습니다"true"
. 페이지를 새로 고칠 때 데이터를 유지하는 올바른 솔루션을 보려면 여기를 참조 하십시오 . 경로가 변경 될 때 데이터를 유지하려면 carloscarcamo의 답변을 확인하십시오. 데이터를 서비스에 저장하기 만하면됩니다.