AngularJS: Binding not working correctly - javascript

I have a login page that displays inside my index.html page. The index.html page has control over a navigation bar that I don't want to show up until the user has successfully logged in. After they login however, the navigation bar ng-show attribute doesn't get updated as I have it in code. Here is the code to illustrate:
<nav class="navbar navbar-inverse" ng-controller="loginController" ng-show={{valid}}>
<div class="collapse navbar-collapse navbar-collapse-links">
<ul class="nav navbar-nav">
<li><a ui-sref="addUser" class="addUser" >Add User</a></li>
<li><a ui-sref="listUser" class="mdUser">Modify User</a></li>
<li><a ui-sref="login" class="mdUser">Logout</a></li>
</ul>
</div>
</nav>
Inside my controller looks like this:
$scope.valid = false;
function login() {
AuthenticationService.Login(vm.user.username, vm.user.password, function (response) {
if (response.success) {
AuthenticationService.SetCredentials(response.token.UserName, response.token.TokenId);
$scope.valid = true;
$location.path('/');
} else {
//FlashService.Error(response.message);
vm.error = response.message;
vm.dataLoading = false;
}
....
)};
}
These is a crude copying and pasting of the code that only contains what I believe is necessary for the current issue.
I can manually change the declaration to true or false and have the navigation bar act correctly. Otherwise, the navigation bar doesn't show up after a valid login attempt, and when I check the html in the console after the login, the ng-show method still shows as false.
QUESTION: Why isn't the valid binding correctly to change after it is reassigned in my success function?

If your AuthenticationService doesn't pump the digest loop, Angular will not update its bindings because it won't know that something has changed.
Try wrapping the body of your .Login callback in a $scope.$apply().
Also, you're navigating away from this view immediately after authenticating the user so the scope where you set $scope.valid = true; is gone.
You can try setting a flag on the root scope like: $rootScope.isLoggedIn = true; and bind against that since the rootscope is kept around for the life of the application.
You're best option is to store the authentication state in your service and binding against that instead. Since services are singletons, that state will be preserved between views as well.

Remove the {{ }} from ng-show. That is one issue with your code.
ng-show="valid"
And check this out for some more info:
http://jaketrent.com/post/when-to-use-curlies-in-angular-directives/

try to change,
<nav class="navbar navbar-inverse" ng-controller="loginController" ng-show={{valid}}>
to
<nav class="navbar navbar-inverse" ng-controller="loginController" ng-show="valid">

Related

How to Change links in node.js

i've been trying for a while to get the tabs on my navigation bar to change (including the link) when a user logs in. The whole thing is a problem on the index page, as you should enter it both logged in and not logged in. i have a in my navigation bar where all tabs are listed via an anchor. This is my app.get of the index:
app.get('/', (req, res)=>{
const {userId} = req.session;
if(userId==undefined){
res.render('index');
}
else{
res.render('index');
}
});
and this Is my header :
<nav>
<div class="logo">Logo</div>
<div class="openMenu"><i class="fa fa-bars"></i></div>
<ul class="mainMenu">
<li>Startseite</li>
<li>Anmelden</li>
<li>Registrieren</li>
<li>Impressum</li>
</ul>
<div class="closeMenu"><i class="fa fa-times"></i></div>
</nav>
I want to change "Anmelden" to "Log out" with this :
<li><form id="abmelden" method="POST" action="/logout">Abmelden</form></li>
And I want to change "Registrieren" to "Dashboard" therefore the link of the a tag and the text must be changed.
Is there a way, where I can use a command like res.send() but to send the depends on, if the user is logged or not
One common technique is to dynamically insert a class on the body tag that is either loggedIn or notLoggedIn. You can then control the rest of your page purely with CSS.
You just insert both the loggedIn and not loggedIn tabs in your navbar and use CSS so one of them is always hidden based on what class is in the tag:
<body class="loggedIn">
or
<body class="notLoggedIn">
Then, you use the same page for both, but use CSS to hide/show things based on the state in the tag. You use conditionals in EJS to insert the right class for the tag based on the logged in state.
You can do this in your index.html page with an EJS conditional to dynamically construct the <body> tag with the right class in it:
<body
<% if (loggedIn) { %>
class="loggedIn" >
<%} else { %>
class="loggedOut" >
<% } %>
I'm not an expert on EJS so if this isn't perfect EJS syntax, you can hopefully see the concept here. When you render your template, you need to pass the loggedIn boolean to the rendering engine so it can dynamically adjust based on that.
Then, you add CSS that shows or hides:
/* hide/show based on login status */
.loggedIn .whenLoggedIn, .loggedOut .whenLoggedOut {display: block;}
.loggedOut .whenLoggedIn, .loggedIn .whenLoggedOut {display: none;}
Then, you put both tabs in your navbar and the class in the <body> tag combined with your CSS will hide/show one of them
<nav>
<div class="logo">Logo</div>
<div class="openMenu"><i class="fa fa-bars"></i></div>
<ul class="mainMenu">
<li>Startseite</li>
<li class="whenLoggedOut">Anmelden</li>
<li class="whenLoggedIn">Ausloggen</li>
<li>Registrieren</li>
<li>Impressum</li>
</ul>
<div class="closeMenu"><i class="fa fa-times"></i></div>
</nav>
Note: You could also use EJS conditionals to just generate the desired tab also so just one tab was generated. But, the technique shown here creates one EJS conditional and then everything else is just HTML/CSS which some people find to be simpler to manage. So, you could have multiple places in the page that have loggedIn and notLoggedIn HTML, but they all work off the class/CSS generates from the one EJS conditional.
By "tab" you mean changing the html page title ?
it's done with this (add it in your template) :
<html>
<head>
<title>title of the doc</title>
</head>
...
</html>
you can add if statements in your template to adapt things.
But it depends of the templating engine you choosed
for twig its done like that :
{% if userId %} <h1>im logged as user {{userId}}</h1> {% endif %}
dont forget to add userId in the render part like so
res.render('index', {userId});
In your code you first check if the user is logged in with:
if(userId==undefined){
If userID is undefined, that means the user is not logged in, so you send them index.js:
res.render('index');
Then you have an else statement for if the user is logged in, but in your else statement you send the exact same thing as you did for a non-logged in user:
else{ res.render('index'); }
So if you want a different menu for a logged-in user you probably need to send them different html.

How to use Angular 9 navigation bar with router-outlet outside the app.component

I'm a beginner in angular.I have created a navigation bar and this is my code inside the app.component
<nav class="navbar navbar-default">
<div class="container-fluid">
<div>
<a routerLink="/login">Login</a>
<a routerLink="/register">Register</a>
</div>
</div>
</nav>
<div>
<router-outlet></router-outlet>
</div>
This works fine as follows
Routing to logging component when logging is clicked
Routing to register component when register is clicked
But when I select another component in my route the navigation bar still exists.So I need my nav bar with logging and register only in my Home component.It should not exist when I routes the other components.I think if i write my code inside another component except the app.component it will work.But how can I use router-outlet and everything on another component.Please help with example.
How can I implement that?
in app.component.html
add to
<nav *ngIf="isHomePage" class="navbar navbar-default"></nav>
in app.component.ts -> ngOnInit()
this.router.events.subscribe(e => {
if (e instanceof RouterEvent) {
this.isHomePage = e.url.split('/').includes('home');
}
});
Hope this will help you.

View is getting initialized again and again

I'm building a dashboard similar to this one Admin Dashboard Theme
I'm implementing the Right Side SideBar as show in the screenshot
My App code structure is something like:
index.html:
<div ui-view=""></div>
main.html
<div ui-view=""></div>
<div ng-include='"app/dashboard/sidebar.html"'></div>
I have done nesting of view in my main.html where I'm injecting different views. Also, since my right side sidebar is fixed, I want it to be common in all the main views. So, I have just included it in my main.html.
Now, the problem is somehow my sidebar.html is getting initialized again and again no matter if I scroll my page down or perform any action inside sidebar. I have verified it by printing console logs for every controller function which are used in sidebar.html view.
This problem is related to my this post: Earlier, I wasn't able to figure out the actual issue.
Following is my controller and jade code:
angular.module('myApp')
.controller('SidebarCtrl', function($scope, $rootScope) {
$scope.message = {};
$scope.addSideBarToggleClass = function() {
console.log("addSideBarToggleClass");
return true;
}
$scope.getStatusClass = function(status) {
console.log("getStatusClass");
return 'is-online';
}
$scope.openChat = function(receiver) {
console.log("openChat");
}
// etc...
});
<aside ng-class="{ 'control-sidebar-open' : addSideBarToggleClass()}"
ng-controller="SidebarCtrl">
<ul>
<li ng-class="{active: isTabSelected('chat')}">
<a data-toggle="tab" ng-click="updateCurrenTab('chat')"></a>
</li>
<li ng-class="{active: isTabSelected('home')}">
<a data-toggle="tab" ng-click="updateCurrenTab('home')"></a>
</li>
</ul>
<div>
<div ng-class="{active: isTabSelected('home')}">
<h3>Recent Activity</h3>
</div>
<div ng-class="{active: isTabSelected('chat')}">
<div>
<h4>Chat {{noOfUsersOnline}}</h4>
<div>Friends
<a href="#" ng-repeat="user in users" ng-click="openChat(user)">
<span ng-class="getStatusClass(user.status)"></span>
{{user.name}}</a>
</div>
</div>
</div>
</div>
</aside>
I see many logs of "addSideBarToggleClass", "getStatusClass" and every time I click on openChat, I see a log of "openChat" and then again "addSideBarToggleClass" and "getStatusClass"
Can anyone please point out what can be the possible problem for this behavior?
You need to familiarize yourself with the concept of a digest loop in Angular.
In short, every time a digest loop runs, all expressions, e.g. {{name}} or ng-show="isActive && isEnabled", that are being "$watched" by Angular are evaluated (sometimes more than once). This means that if you are invoking a function inside an expression:
<div ng-show="isShown()">
$scope.isShown = function(){
console.log("expect to see this text a lot of times");
return true;
};
the function will be executed on every digest loop.
A digest loop runs any time that something in Angular calls $scope.$digest, which by default happens on things like ng-click or ng-change or $http.then, etc..

Angular JS: ng-switch on boolean not working

I am trying to conditionally display a directive based on a boolean value stored in the parent scope. I can't figure out why the below does not work. By, "not work" I mean neither directives are displayed.
<ul class="nav navbar-nav pull-right" ng-switch="userIsAuthenticated">
<account-item item="accountMenuItem" ng-repeat="accountMenuItem in anonymousMenuItems" ng-switch-when="false"></account-item>
<account-item item="accountMenuItem" ng-repeat="accountMenuItem in authenticatedMenuItems" ng-switch-when="true"></account-item>
</ul>
Neither directives are shown even thought "userIsAuthenticated" is set to 'false' in my test case. If I add {{userIsAuthenticated}} above the directives 'false' is output as expected.
I've also tried this:
<ul class="nav navbar-nav pull-right" ng-switch={{userIsAuthenticated}}>
<account-item item="accountMenuItem" ng-repeat="accountMenuItem in anonymousMenuItems" ng-switch-when={{false}}></account-item>
<account-item item="accountMenuItem" ng-repeat="accountMenuItem in authenticatedMenuItems" ng-switch-when={{true}}></account-item>
</ul>
If I remove the conditional ng-switch-when attribute from either of the directives they will display. So I'm know the problem is my ng-switch.
Your usage of ng-switch works in this simplified demo, of course without your account-item directive:
http://plnkr.co/AppN8xmFeIwjaP631lj7
Without seeing the code for account-item, it is hard to guess what might be interfering with it. You might consider using ng-if to handle displaying one item or another.
<ul>
<div ng-if="!userIsAuthenticated">Content when not authenticated</div>
<div ng-if="userIsAuthenticated">Content when authenticated</div>
</ul>
Update
Also make sure you bind to an object property, instead of a primitive boolean. Like: user. authenticated
Since ngSwitchWhen has a priority of 800, you need to set a higher priority to your custom directive (i.e. account-item) in order for it to be compiled before being process by the ngSwitchWhen directive. E.g.:
.directive('accountItem', function () {
return {
...
priority: 900,
...
};
});

How to setup ngclass change when route change occurs in AngularJS?

I am trying to add a class on my main .container class when the route changes.
My current simple solution involves an ng-click on every main menu url (no other urls on the page):
app.controller('MainCtrl', ['$scope', function( $scope ){
$scope.setMain = function( value ){ $scope.isMain = value };
}]);
Then in my html:
<div ng-controller="MainCtrl" class="container" ng-class="{'main': isMain}">
<ul class="main-menu">
<li><a href="#" ng-click="setMain(true)"></li>
<li><a href="#/page-1" ng-click="setMain(false)"></li>
<li><a href="#/page-2" ng-click="setMain(false)"></li>
</ul>
<div ng-view></div>
</div>
This seems to work ok as long as I need to add any more urls the problem is when a user does not click on any of the links and directly accesses a url he does not get the main class.
Is there a better way to do this?
You could use a few different options, but I think the easiest for you would be to setup the $scope.isMain value on controller initialisation by looking at $location. So inside the controller you could have something like:
var loc = $location.path();
if(loc === /* some route rule you require */){
$scope.isMain = true;
}
Have a look here: http://docs.angularjs.org/api/ngRoute/service/$route as the example down the bottom has a few different examples of what sort of data you can access with regards to the route.

Categories

Resources