Scope variables don't reflect in template - angularjs

I have part of an angular app setup as follows:
<section >
<div ng-controller="setHeaderCtrl" class="navbar navbar-default header">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#collapsed-bar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand brand-text" ui-sref="index">
<span class="sports-text">Sports</span>
<span class="gully-text">Gully</span>
</a>
</div>
<div class="collapse navbar-collapse" id="collapsed-bar">
<ul class="nav navbar-nav navbar-left" ng-if="searchingAway">
<li class="local-search-cont">
<input type="text" class="local-type-top" placeholder="Search">
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li ng-if="!userObject">
<a ng-click="showLogin()" class="navbar-txt-block" style="cursor: pointer;">
Login
</a>
</li>
<li ng-if="userObject.user">
<a class="navbar-txt-block" ui-sref="home" style="cursor: pointer;">
Home
</a>
</li>
<li ng-if="userObject">
{{userObject}}
<a class="navbar-txt-block" style="cursor: pointer;">
{{userDetails.first_name}} {{userDetails.last_name}}
</a>
</li>
</ul>
</div>
</div>
</div>
</section>
and my setHeaderCtrl is as follows:
app.controller('setHeaderCtrl',['$scope', '$rootScope', '$http', '$state', 'Page', '$modal',
function($scope, $rootScope, $http, $state, Page, $modal){
$rootScope.$on('userSet', function(){
var authKey = $rootScope.authKey;
$http.defaults.headers.common.Authorization = 'Token '+authKey;
$http.get('/loginCheck/').success(function(data){
$scope.userObject = data;
$scope.userDetails = data.user;
});
});
$scope.userObject = {}
$http.get('/loginCheck/').success(function(data){
$scope.userObject.user = data;
$scope.userDetails = data.user;
console.log($scope.userDetails);
}).error(function(data, status){
if(status == 401){
$scope.userObject.user = undefined;
}
});
$rootScope.$on('setAwayHeader', function(){
$scope.searchingAway = true;
});
$rootScope.$on('setIndexHeader', function(){
$scope.searchingAway = false;
});
$scope.showLogin = function(){
$modal.open({
windowClass: 'modal fade login-modal',
templateUrl: '/static/partials/modals/loginModal.html',
controller: 'loginCtrl'
})
}
}
])
My problem is such that the {{userObject}} or {{userDetails}} never displays. I can guarantee that there's a response from the server because console.log shows the correct data.

The expression ng-if="userObject" is not good, it always true. Replace it by boolean, or by userObject property: ng-if="userObject.user". Jsfiddle

Related

Angular.js and routeprovider tutorial stackskills

I'm currently working through an angular.js tutorial on stackskills but have run into a problem.
It seems as though my use of the routeprovider isn't correct.
Each route is supposed to correlate to a link on a nav bar. However, instead of switching views it always hits the otherwise statement and displays main as opposed to any other view.
When the otherwise statement is removed, none of the views display.
var app = angular.module("computer", ['ngRoute'])
.config(['$routeProvider', function($routeProvider){
$routeProvider.
when('/main', {
templateUrl: 'main.html',
controller:'MainCtrl'
}).
when('/about', {
templateUrl: 'about.html',
controller:'MainCtrl'
}).
when('/services', {
templateUrl: 'services.html',
controller:'ServicesCtrl'
}).
when('/contact', {
templateUrl: 'contact.html',
controller:'ContactCtrl'
}).
otherwise({redirectTo: "/main"})
}])
.controller('MainCtrl', ['$scope', function($scope){
}])
.controller('ServicesCtrl', ['$scope', function($scope){
}])
.controller('ContactCtrl', ['$scope', function($scope){
}]);
This is the div that houses the nav bar and links for the views
<div class="container">
<header class="masthead">
<h3 class="text-muted">Computer Solutions</h3>
<nav class="navbar navbar-expand-md navbar-light bg-light rounded mb-3">
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarCollapse">
<ul class="navbar-nav text-md-center nav-justified w-100">
<li class="nav-item active">
<a class="nav-link" href="#/main">Home <span class="sr-only">(current)</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#/about">About</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#/services">Services</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#/contact">Contact</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="http://example.com" id="dropdown01" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Dropdown</a>
<div class="dropdown-menu" aria-labelledby="dropdown01">
<a class="dropdown-item" href="#">Action</a>
<a class="dropdown-item" href="#">Another action</a>
<a class="dropdown-item" href="#">Something else here</a>
</div>
</li>
</ul>
</div>
</nav>
</header>
</div>
<div ng-controller='MainCtrl'>
<div ng-view></div>
</div>
Any advice would be greatly appreciated!
Turns out my syntax was off "#!/about" is the current method of calling a view

UI-Router 1.0.0-beta.2 and UI-Bootstrap 2.1.4 dropdown not closing

I'm using ui-route ui-sref in my links with the navbar using UI-Bootstrap dropdowns and if I use the anchor tag with href, the dropdown closes on click, but the anchor tags with ui-sref does not close the dropdown. I've got the following plnkr with it showing the bug.
Angular Code
angular.module('app', ['ui.bootstrap', 'ui.router'])
.config(appRoute)
.controller('myController', myController);
appRoute.$inject = ['$stateProvider'];
function appRoute($stateProvider) {
$stateProvider.state('index', {
url: '/index',
template: '<h1>indexRoute</h1>'
})
.state('other', {
url: '/other',
template: '<h1>otherRoute</h1>'
})
}
function myController() {
var ctrl = this;
ctrl.title = 'Title';
ctrl.user = 'User#user.com';
ctrl.test = test;
ctrl.test2 = test2;
function test() {
console.log('TEST LINK!')
}
function test2() {
console.log('TEST 2')
}
}
HTML
<body ng-controller="myController as $ctrl" style="{padding-top: 70px;}">
<nav id="isec-menu" class="navbar navbar-default navbar-fixed-top">
<div class="container-fluid">
<div class="navbar-header">
<div class="intelisecure-header">
<span>{{$ctrl.title}}</span>
</div>
</div>
<div class="collapse navbar-collapse navbar-right">
<ul class="nav navbar-nav">
<li id="usermenu" class="dropdown user-menu-dropdown" uib-dropdown="">
<a href="" class="uib-dropdown-toggle username" uib-dropdown-toggle="">
<i class="fa fa-user fa-fw"></i>
{{$ctrl.user}} <span class="caret"></span>
</a>
<ul class="dropdown-menu" uib-dropdown-menu="" role="menu">
<li role="menuitem">
<a href="/index" ng-click="$ctrl.test()">
<i class="fa fa-fw fa-sign-out menu-icon"></i>
<span class="menu-text">index href</span>
</a>
</li>
<li role="menuitem">
<a ui-sref="other" ng-click="$ctrl.test2()">
<i class="fa fa-fw fa-sign-out menu-icon"></i>
<span class="menu-text">other sref</span>
</a>
</li>
<li role="menuitem">
<a href="" ng-click="$ctrl.logout()">
<i class="fa fa-fw fa-sign-out menu-icon"></i>
<span class="menu-text">Logout</span>
</a>
</li>
</ul>
</li>
</ul>
</div>
</div>
</nav>
<ui-view>
<div>
test
</div>
</ui-view>
</body>
Not perfectly built, I was trying to see if I could replicate the issue with my
https://plnkr.co/edit/Rz3AbgnYnWI34DjuByY6?p=preview
Apparently this was a known issue and was resolved by updating to UI-Router 1.0.0-beta.3

Unknown provider: NavbarController - yeoman generator

I generated a project with Generator Angular Fullstack v3.0.2. I opend the server, all worked well. But on the client side I have a problem, I received an error in console error:
[$injector:unpr] Unknown provider: $locationAuthProvider <-
$locationAuth <- NavbarController
Controller
class NavbarController {
//start-non-standard
menu = [{
'title': 'Home',
'link': '/'
}];
isCollapsed = true;
//end-non-standard
constructor($locationAuth) {
this.$location = $location;
this.isLoggedIn = Auth.isLoggedIn;
this.isAdmin = Auth.isAdmin;
this.getCurrentUser = Auth.getCurrentUser;
}
isActive(route) {
return route === this.$location.path();
}
}
angular.module('rideSharingApp')
.controller('NavbarController', NavbarController);
HTML
<div class="navbar navbar-default navbar-static-top" ng-controller="NavbarController">
<div class="container">
<div class="navbar-header">
<button class="navbar-toggle" type="button" ng-click="nav.isCollapsed = !nav.isCollapsed">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
ride-sharing
</div>
<div collapse="nav.isCollapsed" class="navbar-collapse collapse" id="navbar-main">
<ul class="nav navbar-nav">
<li ng-repeat="item in nav.menu" ng-class="{active: nav.isActive(item.link)}">
<a ng-href="{{item.link}}">{{item.title}}</a>
</li>
<li ng-show="nav.isAdmin()" ng-class="{active: nav.isActive('/admin')}">Admin</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li ng-hide="nav.isLoggedIn()" ng-class="{active: nav.isActive('/signup')}">Sign up</li>
<li ng-hide="nav.isLoggedIn()" ng-class="{active: nav.isActive('/login')}">Login</li>
<li ng-show="nav.isLoggedIn()"><p class="navbar-text">Hello {{ nav.getCurrentUser().name }}</p> </li>
<li ng-show="nav.isLoggedIn()" ng-class="{active: nav.isActive('/settings')}"><span class="glyphicon glyphicon-cog"></span></li>
<li ng-show="nav.isLoggedIn()">Logout</li>
</ul>
</div>
</div>
</div>
I don't know very well angular, so can you help me to fix this error?
Thanks.
$locationAuth should be ($location, Auth).
I think this may also be fixed in a more recent commit so you might be able to just update your generator.

How to modify HTML content based on angular controller

I am trying to build a login page and a functionality page using angularjs SPA.
I have following controller:
- LoginController
- PredictionController
And following single page:
- Home.html : Binded to LoginController
- trend.html : Binded to PredictionController
- index.html : Has no controller
I have navigation panel in index.html and I want to modify(add or remove) number of tabs based on login. I don't want to write navigation panel logic in each page as it is reusable. I am unable to figure out way to do this using additional controller because I am using ng-route which I guess won't allow me to use multiple controller for same page.
Here is my html code snippet for index.html:
<body>
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#/">MyProject</a>
</div>
<div id="navbar" class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="active">Home</li>
<li>Trend</li>
</ul>
</div><!--/.nav-collapse -->
</div>
</nav>
<div ng-app="chartApp">
<div ng-view></div>
</div>
</body>
Here is the code for controller:
var app = angular.module('chartApp', ['ngRoute']);
app.factory('UserVerified', function() {
return
{bool: false};
});
app.config(function ($routeProvider) {
$routeProvider
.when('/',{
templateUrl: 'pages/home.html',
controller: 'LoginController'
})
.when('/Trend', {
templateUrl: 'pages/trend.html',
controller: 'PredictionController'
})
});
app.controller('LoginController', ['$scope', '$http', 'UserVerified', function($scope, $http, UserVerified){
$scope.hasPermission = UserVerified.bool;
$scope.getAuthentication = function(){
console.log($scope.userId, $scope.pwd)
$http.get('/getAuth', {
params: { user_id: $scope.userId, pwd: $scope.pwd }
}).success(function (response){
console.log(response);
UserVerified.bool = response;
$scope.hasPermission = UserVerified.bool;
});
}
}]);
I'm not sure if the information is enough please edit or let me know if i'm missing some information.
I believe you're going to have to move your ng-app directive up to the body, and create a NavigationController which can require your UserVerified factory and help maintain the state of the navigation.
You could add the ng-controller directive to your navbar explicitly, and your router should work the same.
The HTML might look something like this.
<body ng-app="chartApp">
<nav ng-controller="NavigationController" class="navbar navbar-inverse navbar-fixed-top">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<!-- Only display if $scope.loggedIn -->
<a ng-show="loggedIn" class="navbar-brand" href="#/">MyProject</a>
</div>
<div id="navbar" class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="active">Home</li>
<li>Trend</li>
</ul>
</div><!--/.nav-collapse -->
</div>
</nav>
<div ng-view></div>
</body>
NavigationController
app.controller('NavigationController', function($scope, UserVerified) {
$scope.$watch(function() {
return UserVerified.bool;
}, function(state, oldState) {
$scope.loggedIn = state;
});
});

AngularJS Factory and Parse.com User Authentication

I am playing around with AngularJS using Parse.com as it's backend and am having an issue when I try go authenticate and deuthenticate with Parse. I am abe to do both these functions, but my views don't update.
app.factory('hsUser', ['$http', function($http){
var dataObject = null;
return {
get: function()
{
var tmpData = Parse.User.current();
console.log(tmpData);
if(tmpData && dataObject == null)
{
dataObject = {};
keys = Object.keys(tmpData);
keys.forEach(function(value)
{
dataObject[value] = tmpData[value];
});
console.log(dataObject);
}
return dataObject;
},
authenticate: function(username, password)
{
console.log('auth');
Parse.User.logIn(username, password, {
success: function(userData) {
dataObject = {};
keys = Object.keys(userData);
keys.forEach(function(value)
{
dataObject[value] = userData[value];
});
},
error: function(userData, errorData) {
console.log(errorData);
}
});
},
deauthenticate: function()
{
Parse.User.logOut();
dataObject = Parse.User.current();
},
doRegister: function(registration)
{
console.log(registration);
return {
success: true
}
}
}
}]);
Here are my controllers.
app.controller('HeaderController', ['hsConfig','hsUser', function( hsConfig, hsUser)
{
this.config = hsConfig.get();
this.user = hsUser.get();
}]);
app.controller('AuthController', ['hsUser', function( hsUser)
{
this.user = hsUser.get();
this.authUser = {
emailAddress: "testinguser",
password: "testinguser",
remember: false,
}
this.authenticate = function()
{
hsUser.authenticate(this.authUser.emailAddress, this.authUser.password);
}
this.deauthenticate = function()
{
this.user = hsUser.deauthenticate();
console.log('Deauthenticated')
}
}]);
Here is the HTML for the directive that creates the navbar
<div class="header" ng-controller="HeaderController as headCtrl">
<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">{{ headCtrl.config.brand }}</a>
</div>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav navbar-right" ng-hide="headCtrl.user">
<li class="dropdown" ng-controller="AuthController as authCtrl">
<a class="dropdown-toggle" href data-toggle="dropdown">
Sign In
<strong class="caret"></strong>
</a>
<div class="dropdown-menu auth-form-container" style="padding: 15px; padding-bottom: 0px;" >
<form role="form" ng-submit="authCtrl.authenticate();">
<div class="form-group">
<label for="exampleInputEmail1">Email address</label>
<input type="email" class="form-control" placeholder="Enter email" ng-model="authCtrl.authUser.emailAddress" >
</div>
<div class="form-group">
<label for="exampleInputPassword1">Password</label>
<input type="password" class="form-control" placeholder="Password" ng-model="authCtrl.authUser.password">
</div>
<div class="form-group checkbox">
<label>
<input type="checkbox" ng-model="authCtrl.authUser.remember"> Remember Me
</label>
</div>
<div class="form-group">
<button class="btn btn-primary btn-full">Sign In</button>
</div>
</form>
</div>
</li>
<li class="divider-vertical"></li>
<li>Register</li>
</ul>
<ul class="nav navbar-nav navbar-right" ng-show="headCtrl.user">
<li>Profile</li>
<li class="divider-vertical"></li>
<li ng-controller="AuthController as authCtrl">
<a href ng-click="authCtrl.deauthenticate();">Sign Out</a>
</li>
</ul>
</div>
</div>
</nav>
</div>
The entire project including Parse keys can be found here. I'll delete the keys once I figure out wtf my problem is.
https://github.com/thenetimp/hackerspace
If anyone can point me into what I am doing wrong and explain it so I can understand what I need to do with other Models I would greatly appreciate it.
whenever you update the model outside of angulars context, I.e in the callback of a promise, you need to use $scope.apply to notify angular.

Resources