For quick reading, the problem is simplified under "The problem", and for further information keep going down for background and notes before answering. Thank you!
I want to delete the instance of a controller when refreshing the page or when moving to a different view and then returning to the same view through the navigator (nav.html
). In fact, every time view X.html
is visited, I want the program to check if X-controller.js
exists, and if it does delete it before making a new instance.
How far am I going here, is it a 2 line solution I failed to find online or am I looking at hours of coding to make this work?
My project uses the $routeProvider
service, not the the ng-controller
directive. Once the app launches there are constantly two views, one on the top where you can navigate back and forth through the controllers "Home - Contact - Support" (logically, nav.html
), and one on the bottom which is the "Home" or "Contact" and so on.
I haven't had any problems with this arrangement until the code begun making massive calculations. The same instance of the controller is updated with more data than it should, calculates for previous data that was discarded, and so on. I've read online about deleting the controller but as far as I know it's not that easy.
Notes before answering the question:
ng-controller
is used and not $routeProvider
then it's not an option for me. There are over 20 views and many sections of code which triggers redirection to a different view with a different controller using event listeners. I'm not currently planning on changing $routeProvider
to ng-controller
.$routeProvider
configuration or one view and controller is needed let me know and I'll include that code with the classified sections replaced with similar dummy code.Clarification Edit
I'll illustrate with an example. Assume X.html
is a view controlled by XCtrl.js
. $scope.test
is initiated in the beginning $scope.test = 2
of that controller, and once a button in the view is clicked $scope.test
becomes 3. Also, the X view displays $scope.test
all the time. So I moved to that view, clicked the button, and saw that 3 is displayed on the screen. Then I moved to "Home" through the navigator, then back to "X", and 3 is still displayed. But what I want is 2 to be displayed, and not 3. I want everything to be renewed in that controller.
Solution
Eventually I used a different technique to solve this. All the data saved in the local storage was affecting the $scope variables (there were too many variables to track that I didn't notice this). To solve the issue I cleared the local storage key localStorageService.set('keyUsed', []);
once the view controlled by controller X is visited. Assume an init function, so the line of code clearing the local storage was placed in the top of that function.
I'm still marking the correct solution from the answers below for the problem I initially thought I had.
Always have a '.' in your ng-models!
-- Miško Hevery (father of AngularJS)
Most likely you have an issue with $scope.test
and not with controller itself. If your template x.html
refers the value of test
as {{test}}
(without any prefix) then most probably you are referring the test
of the wrong scope. It usually happens due to prototypical chain of scopes that extend one another and fallback to prototype property value. In this case, choose something unique for XCtrl
controller and put all your state inside this controller to that namespace. For example, use x
as namespace
$scope.x = {};
$scope.x.test = 2;
instead of just
$scope.test = 2;
Then in x.html
refer the value as
{{x.test}}
This is one of the Angular best practices.
Another best practice, that may solve your issue, is actually not using $scope
at all, but use controller instance itself for storing state in junction with controllerAs
syntax:
index.html
<!DOCTYPE html>
<html ng-app="app">
<head>
<script data-require="[email protected]" data-semver="1.5.8" src="https://code.angularjs.org/1.5.8/angular.min.js"></script>
<script data-require="[email protected]" data-semver="1.5.8" src="https://code.angularjs.org/1.5.8/angular-route.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-view>
</body>
</html>
script.js
angular.module('app', ['ngRoute'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/x', {
controller: 'xCtrl',
controllerAs: 'x',
templateUrl: 'x.html'
})
.when('/y', {
controller: 'yCtrl',
controllerAs: 'y',
templateUrl: 'y.html'
})
.otherwise({
redirectTo: '/x'
})
}])
.controller('xCtrl', [function() {
var x = this;
x.test = 2;
x.doSomething = function() {
x.test ++;
};
}])
.controller('yCtrl', [function() {
var y = this;
y.hello = 'Hello';
}])
x.html
<h1>X.html</h1>
<p>test = {{x.test}}</p>
<button ng-click="x.doSomething()">+1</button>
<a href="#/y">Link to Y</a>
y.html
<h1>Y.html</h1>
<p>{{y.hello}}</p>
<a href="#/x">Link to X</a>
Live Demo:
https://plnkr.co/edit/EpUn94uWMliTaG5mvPxv?p=preview
Links: