3

I am not getting why it is not working.

I am trying to show Login/Logout link based on condtion by calling a method from html. in console I can see it is returning "true", but it never changes the link to "Logout". it is always "Login" on the screen

<ul class="nav navbar-nav navbar-right">
    <li class="nav-item dropdown" [hidden]="!authenticated()">
        <a class="nav-link dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
            <i class="fa fa-user" aria-hidden="true"></i> Welcome, {{user}}!
        </a>
        <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
            <a class="nav-link dropdown-item" (click)="logout()">Logout</a>
        </div>
    </li>
    <li class="nav-item dropdown" [hidden]="authenticated()">
        <a routerLinkActive="active" routerLink="/login">Login</a>
    </li>
</ul>

component.ts

authenticated() {
    console.log(localStorage.getItem('authenticated'));
    if(localStorage.getItem('authenticated') === 'true') {
        console.log("YES");
        return true;
    } else {
        console.log("NO");
        return false;    
    }
}

Before clicking on Login link enter image description here

After click on Login enter image description here

After entering correct username/password (Her you can see in console it returns true) enter image description here

David Walschots
  • 12,279
  • 5
  • 36
  • 59
SK.
  • 1,390
  • 2
  • 28
  • 59

2 Answers2

2

First of all you should not call a function with *ngIf directive, as it will run with every change detection. This can lead to performance overhead. Either use a variable or convert your method into a getter property e.g.

get authenticated(): boolean {
    return localStorage.getItem('authenticated') === true;
}

Secondly, use *ngIf instead of [hidden]:

<ul class="nav navbar-nav navbar-right">
    <li class="nav-item dropdown" *ngIf="authenticated">
        <a class="nav-link dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
            <i class="fa fa-user" aria-hidden="true"></i> Welcome, {{user}}!
        </a>
        <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
            <a class="nav-link dropdown-item" (click)="logout()">Logout</a>
        </div>
    </li>
    <li class="nav-item dropdown" *ngIf="!authenticated">
        <a routerLinkActive="active" routerLink="/login">Login</a>
    </li>
</ul>
David Walschots
  • 12,279
  • 5
  • 36
  • 59
FAISAL
  • 33,618
  • 10
  • 97
  • 105
  • 2
    I'm unable to see the performance advantage of using a getter property over a function. Why is this better? – David Walschots Apr 30 '18 at 19:40
  • @david-walschots maybe this will help: https://stackoverflow.com/a/46903095/1791913 – FAISAL Apr 30 '18 at 19:50
  • 1
    Yes. I understand that a function call has a certain overhead (even though that overhead is probably very small when the function doesn't do much). However, a getter property is in fact nothing more than a function, which is why I was asking. – David Walschots Apr 30 '18 at 21:14
1

Replace hidden directive with *ngIf directive.

<ul class="nav navbar-nav navbar-right">
    <li class="nav-item dropdown" *ngIf="!authenticated()">
        <a class="nav-link dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
            <i class="fa fa-user" aria-hidden="true"></i> Welcome, {{user}}!
        </a>
        <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
            <a class="nav-link dropdown-item" (click)="logout()">Logout</a>
        </div>
    </li>
    <li class="nav-item dropdown" *ngIf="authenticated()">
        <a routerLinkActive="active" routerLink="/login">Login</a>
    </li>
</ul>

It's functinally the same, but ng-if directive remove the element from DOM, and hidden attribute just hides it.

Another solution is to change your method to this:

authenticated() {
    console.log(localStorage.getItem('authenticated'));
    if(localStorage.getItem('authenticated') === 'true') {
        console.log("YES");
        return true;
    } else {
        console.log("NO");
        return null;    
    }
}
David Walschots
  • 12,279
  • 5
  • 36
  • 59
Roberto Zvjerković
  • 9,657
  • 4
  • 26
  • 47
  • As it is integrated with spring, database, I am not sure how I can create a stackblitz – SK. Apr 30 '18 at 18:01
  • Well nothing here is connected to the DB, even your `authenticated` method doesn't talk to the back end. You can mock the needed data. But the main point is just making you rewrite the code, which sometimes helps in finding the mistake by itself. – Roberto Zvjerković Apr 30 '18 at 18:03
  • And if you can reproduce the error, I will have much easier time finding it. – Roberto Zvjerković Apr 30 '18 at 18:05
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/170103/discussion-between-ritaj-and-sk). – Roberto Zvjerković Apr 30 '18 at 18:06
  • I am a stupid. both your and my code is fine. But I did a mistake. If oyu see my code, the Logout link is in a dropdown. That is why it is not showing up... – SK. Apr 30 '18 at 18:07
  • Haha. Well, happens to everybody! But do learn to use `*ngIf` (and what @Faisal said), so the time was not wasted! – Roberto Zvjerković Apr 30 '18 at 18:09