basically my issue is that I have a AngularJS view (home.html) which contains a variable in double brackets like so: {{message}}
When the $scope.message variable is modified, the view with does not update, although it should? I have tried adding $scope.$apply() which results in an exception along the lines of 'Action in Progress'
Check my code below. The {{message}} part in home.html is not being updated when $scope.doLogin is called in MainCtrl, even though I have set $scope.message to a new value in that function.
Any help is greatly appreciated and if any further info is needed, please ask.
index.html
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href=".3.5/css/bootstrap.min.css" rel="stylesheet">
<link href="stylesheet.css" rel="stylesheet">
<script src=".11.3/jquery.min.js"></script>
<script src=".js/1.4.4/angular.min.js"></script>
<script src=".js/1.4.4/angular-route.min.js"></script>
<base href="/">
<script src=".3.9/ngStorage.js"></script>
<script src=".io-1.3.5.js"></script>
</head>
<body>
<div ng-controller="MainCtrl">
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="#">TriviaAttack</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<form id="loginForm" class="navbar-form navbar-right">
<div class="form-group">
<input type="text" placeholder="Email" class="form-control" ng-model="loginData.username">
</div>
<div class="form-group">
<input type="text" placeholder="Password" class="form-control" ng-model="loginData.password">
</div>
<div class="form-group">
<button type="submit" class="btn btn-success" ng-click="doLogin()">Sign In</button>
</div>
</form>
</div>
</div>
</nav>
</div>
<div ng-view>
</div>
</div>
<script src="./app/app.js"></script>
<script src=".3.5/js/bootstrap.min.js">
</body>
</html>
home.html
<div>
<h1>Wele to the Home Page</h1>
<p>{{message}}</p>
</div>
app.js
var myApp = angular.module('myApp',['ngRoute', 'ngStorage']);
myApp.controller('MainCtrl', ['$rootScope', '$scope', '$location',
function($rootScope, $scope, $location) {
$scope.message = 'testing message';
$scope.loginData = {
username: '',
password: '',
loggedIn: false
}
$scope.doLogin = function() {
$scope.message = 'message changed!';
$scope.$apply();
Auth.doLogin($scope.loginData.username, $scope.loginData.password)
.success(function(data) {
if (data.success) {
AuthToken.setToken(data.token);
$location.path('/home');
console.log($scope.loginData.loggedIn);
}
});
$scope.loginData = {};
}
}]);
//Middleware for all requests which adds the users token to the HTTP header.
myApp.factory('TokenInterceptor', ['$q', '$location', '$localStorage',
function($q, $location, $localStorage) {
//On each request, check if the user is logged in with a valid token.
var interceptor = {
request: function(config) {
config.headers['X-Authorization-Token'] = $localStorage.token;
return config;
},
responseError: function(response) {
if(response.status === 401 || response.status === 403) {
$location.path('/login');
}
return $q.reject(response);
}
};
return interceptor;
}]);
myApp.config(['$routeProvider','$locationProvider','$httpProvider',
function($routeProvider, $locationProvider, $httpProvider) {
$routeProvider.
when('/', {
templateUrl: './app/views/landingpage.html',
controller: 'MainCtrl'
}).
when('/home', {
templateUrl: './app/views/home.html',
controller: 'MainCtrl'
}).
otherwise({
redirectTo: '/'
});
$locationProvider.html5Mode(true);
$httpProvider.interceptors.push('TokenInterceptor');
}
]);
console.log('app.js loaded!');
basically my issue is that I have a AngularJS view (home.html) which contains a variable in double brackets like so: {{message}}
When the $scope.message variable is modified, the view with does not update, although it should? I have tried adding $scope.$apply() which results in an exception along the lines of 'Action in Progress'
Check my code below. The {{message}} part in home.html is not being updated when $scope.doLogin is called in MainCtrl, even though I have set $scope.message to a new value in that function.
Any help is greatly appreciated and if any further info is needed, please ask.
index.html
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://maxcdn.bootstrapcdn./bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet">
<link href="stylesheet.css" rel="stylesheet">
<script src="https://ajax.googleapis./ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/angular.js/1.4.4/angular.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/angular.js/1.4.4/angular-route.min.js"></script>
<base href="/">
<script src="https://cdnjs.cloudflare./ajax/libs/ngStorage/0.3.9/ngStorage.js"></script>
<script src="https://cdn.socket.io/socket.io-1.3.5.js"></script>
</head>
<body>
<div ng-controller="MainCtrl">
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="#">TriviaAttack</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<form id="loginForm" class="navbar-form navbar-right">
<div class="form-group">
<input type="text" placeholder="Email" class="form-control" ng-model="loginData.username">
</div>
<div class="form-group">
<input type="text" placeholder="Password" class="form-control" ng-model="loginData.password">
</div>
<div class="form-group">
<button type="submit" class="btn btn-success" ng-click="doLogin()">Sign In</button>
</div>
</form>
</div>
</div>
</nav>
</div>
<div ng-view>
</div>
</div>
<script src="./app/app.js"></script>
<script src="https://maxcdn.bootstrapcdn./bootstrap/3.3.5/js/bootstrap.min.js">
</body>
</html>
home.html
<div>
<h1>Wele to the Home Page</h1>
<p>{{message}}</p>
</div>
app.js
var myApp = angular.module('myApp',['ngRoute', 'ngStorage']);
myApp.controller('MainCtrl', ['$rootScope', '$scope', '$location',
function($rootScope, $scope, $location) {
$scope.message = 'testing message';
$scope.loginData = {
username: '',
password: '',
loggedIn: false
}
$scope.doLogin = function() {
$scope.message = 'message changed!';
$scope.$apply();
Auth.doLogin($scope.loginData.username, $scope.loginData.password)
.success(function(data) {
if (data.success) {
AuthToken.setToken(data.token);
$location.path('/home');
console.log($scope.loginData.loggedIn);
}
});
$scope.loginData = {};
}
}]);
//Middleware for all requests which adds the users token to the HTTP header.
myApp.factory('TokenInterceptor', ['$q', '$location', '$localStorage',
function($q, $location, $localStorage) {
//On each request, check if the user is logged in with a valid token.
var interceptor = {
request: function(config) {
config.headers['X-Authorization-Token'] = $localStorage.token;
return config;
},
responseError: function(response) {
if(response.status === 401 || response.status === 403) {
$location.path('/login');
}
return $q.reject(response);
}
};
return interceptor;
}]);
myApp.config(['$routeProvider','$locationProvider','$httpProvider',
function($routeProvider, $locationProvider, $httpProvider) {
$routeProvider.
when('/', {
templateUrl: './app/views/landingpage.html',
controller: 'MainCtrl'
}).
when('/home', {
templateUrl: './app/views/home.html',
controller: 'MainCtrl'
}).
otherwise({
redirectTo: '/'
});
$locationProvider.html5Mode(true);
$httpProvider.interceptors.push('TokenInterceptor');
}
]);
console.log('app.js loaded!');
Share
Improve this question
asked Sep 7, 2015 at 5:26
JohnWickJohnWick
5,1499 gold badges40 silver badges79 bronze badges
4
-
All your views are using their own
MainCtrl
and have their own$scope
so when you calldoLogin
from the the login form it will only update themessage
in it's own scope, not the controller of theng-view
. – logee Commented Sep 7, 2015 at 5:35 - Hi, so what I am trying to do is not possible? Or what is your suggested solution. I appreciate your response btw thank you :) – JohnWick Commented Sep 7, 2015 at 5:49
- See Angular: Share data between controllers. In a nutshell, return an object from a factory and work off that in the controllers. Let us know if it doesn't help. – logee Commented Sep 7, 2015 at 5:55
- Thanks for the link. I will change my code a bit and implement the pattern and let you know if it works. – JohnWick Commented Sep 7, 2015 at 5:56
2 Answers
Reset to default 2Each time a view is loaded ,the controller code with new scope executes so the new message is not reflected. So the flow be like landingPage's controller which is MainCtrl with its scope when $scope.doLogin is executed will change the $scope.message variable to "Message Changed" and upon changing location to home , the MainCtrl is assigned to home page with new scope which would continue executing the very first line of MainCtrl i.e.
$scope.message = 'testing message';
As you have decided to use mon controller for login and home pages
Try removing controller option in
when('/', {
templateUrl: './app/views/landingpage.html',
controller: 'MainCtrl'
}).
when('/home', {
templateUrl: './app/views/home.html',
controller: 'MainCtrl'
})
And assign controller in
<div ng-controller="MainCtrl">
<!--omitted-->
<div ng-view></div>
</div>
Or else other options would be to pass parameters or use ui-router wherein nested views would automatically inherit from parent controllers without rerunning the controller logic.
Problem is in controller coverage
<div ng-controller="MainCtrl">
<!--omitted-->
</div>
<div ng-view></div>
Your $scope.message is tight to your MainCtrl, so when ng-view
is populated, you except that it has MainCtrl
, but indeed it's outside of that div, so just doesn't see that variable, to make it work, insert ng-view to MainCtrl div like shown below
<div ng-controller="MainCtrl">
<!--omitted-->
<div ng-view></div>
</div>
But here's the actual problem
You tend to use ng-route but you don't have any route configurations, ng-view
will never be populated with home.html
unless you configure you routeProvider, first of all, make some routes like described here, perform your form action, redirect to page and populate views accordingly, it should work.