I know this is long, but it appears something specific in what I'm doing in the more complex scenario is causing the issue. All simple examples I attempt work fine.
I have an application setup using angularjs and laravel four.
The home page is rendered via laravel routing:
Route::get('/', function() {
return View::make('app');
});
app.php returns the website skeleton with the following structure:
<!doctype html>
<html lang="en" ng-app="app">
<head>
<script src="/js/angular.js"></script>
<script src="/js/angular-sanitize.js"></script>
<script src="/js/angular-ui-router.js"></script>
<script src="/js/app.js"></script>
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top" ng-controller="NavController">
<div class="navbar-inner">
<div class="container-fluid">
<button class="button pull-right" ng-click="logout()">Logout</button>
<p class="navbar-text pull-right" >
Logged in as <a href="#" class="navbar-link">{{ currentUser.email }} id is : {{ currentUser.userId }}</a>
</p>
</div>
</div>
</div>
</div>
<div class="row-fluid offset05">
<div id="view" ng-view></div>
</div>
</div>
</body>
</html>
basics of app.js:
var app = angular.module("app", ['ngSanitize','ui.state','ui.bootstrap']);
the user is initially routed to a login template, at which point a LoginController updates the user information which resides in UserService.
app.controller("LoginController", function($scope,$rootScope, $location, AuthenticationService, UserService) {
$scope.credentials = { email: "", password: "" };
$scope.login = function() {
AuthenticationService.login($scope.credentials).success(function() {
$location.path('/home');
});
};
});
Authentication Service updates the UserService variable appropriately:
app.factory("AuthenticationService", function($rootScope, $http, $sanitize, SessionService, FlashService, CSRF_TOKEN, UserService) {
return {
login: function(credentials) {
var login = $http.post("/auth/login", sanitizeCredentials(credentials));
login.success(function(data){
UserService.currentUser = data.user;
});
return login;
}
});
NavController (controller for navigation bar seen above) binds its scope to the UserService.currentUser.
app.controller("NavController",function($scope, UserService, AuthenticationService,$location){
$scope.currentUser = UserService.getCurrentUser();
});
Relevant parts of UserService:
app.factory("UserService", function($http){
var _currentUser = {}
return{
currentUser: _currentUser,
getCurrentUser: function() {
return _currentUser;}
};
});
When the user logs in, their user email and userid should appear in the navigation bar.
If I create an example which strictly uses javascript/html there are no issues with the binding.
With the mechanics/structure mentioned above, the navbar does not respond to the changes in the UserService current user variable until the entire page is reloaded.
After the user logs in, I can verify that the UserController and UserService both update the currentUser appropriately. In spite of this, the NavController will not reflect the updated user unless I reload the whole page.
I assume this is becuase the NavController is now re-running with the updated information, but why isn't normal binding working?
I guess this has something to do with the fact that the navigation bar is loaded via php.
My question is how can I either: a) make the binding via the service work appropriately or b) reload the NavController when necessary (post login/logout)
There are a couple ways you can handle this.
$scope
to the service itself, in which case any changes to that model will be picked up automatically$watch
In this example, you can see both techniques: (http://plnkr.co/edit/bhBXMr?p=preview):
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, AuthenticationService, UserService) {
$scope.user = UserService;
$scope.login = function(){
AuthenticationService.login();
}
// watch the service for changes to currentUser
$scope.$watch(function(){
return UserService.currentUser;
}, function(currentUser){
$scope.currentUser = currentUser;
}, true);
});
app.service('AuthenticationService', function($http, UserService){
return {
login: function(){
$http.get('data.json').success(function(data){
UserService.currentUser = data;
});
}
};
});
app.service('UserService', function($rootScope){
return {
currentUser: null
};
});
HTML Markup:
<body ng-controller="MainCtrl">
<button ng-click="login()">Login</button>
<div>Current User: {{user.currentUser}}</div>
<!-- from the watch -->
<div>Current User: {{currentUser}}</div>
</body>