updating routes in navbar - navbar

I'm writing a public web page at work, with angular 9, where the array of possible routes depends on the user's role.
I get the role from an HTTP request and the response updates an observable, that will be passed to a child component.
the problem is: the response is received but the template is not updated.
here it is components code:
#Component({
selector: 'navbar',
template: `<nav-template [routesArray]="routesArrayObservable | async"></nav-template>`
})
export class NavbarComponent implements OnInit {
private routesSubject: BehaviorSubject<AppRoute[]>;
routesArrayObservable: Observable<AppRoute[]>;
constructor(private accountService: AccountService) {
this.routesSubject = new BehaviorSubject<AppRoute[]>(null);
this.routesArrayObservable = this.routesSubject.asObservable();
}
ngOnInit(): void {
this.accountService.subscribableRole().subscribe((actualRole: string) => {
this.routesSubject.next(ruoli[actualRole]);
});
}
}
#Component({
selector: 'nav-template',
templateUrl: './navbar.component.html',
})
export class NavbarTemplate implements OnInit, OnChanges{
#Input() routesArray: AppRoute[];
user: Observable<User>;
constructor(private accountService: AccountService){
this.user = null;
}
ngOnInit(): void {
this.user = this.accountService.user;
}
ngOnChanges(changes: SimpleChanges){
for (let propName in changes) {
if (propName === 'routesArray'){
this.routesArray = changes[propName].currentValue;
}
}
}
}
and HTML template:
<nav class="navbar navbar-expand navbar-dark bg-dark" *ngIf="user | async">
<div class="navbar-nav" *ngIf="routesArray.length">
<a *ngFor="let route of routesArray" class="nav-item nav-link"
routerLink="{{ route.routerLink }}">{{ route.name }}</a>
</div>
<div class="nav-account">
<nav-account></nav-account>
</div>
</nav>

resolved: the code in the subscribe() function wasn't in the NgZone.
I'm including another question with more data and explanation.
solution

Related

Angular 13 Parent-Child not Communicating

Trying to get an array from a parent component to a child component. The Angular docs make it look really simple but I'm not sure what I'm doing wrong. The variable is activePost. Angular version is 13
Parent ts file (HomepageComponent):
import { Component, OnInit } from '#angular/core';
import { PostService } from 'src/app/services/post.service';
import { map } from 'rxjs/operators';
import { Post } from 'src/app/models/post.model';
import { ActivatedRouteSnapshot, Router } from '#angular/router';
import { PostDisplayComponent } from '../components/post-display/post-display.component';
#Component({
selector: 'app-homepage',
templateUrl: './homepage.component.html',
styleUrls: ['./homepage.component.scss']
})
export class HomepageComponent implements OnInit {
posts?: Post[];
category?:'';
currentpost?: Post;
currentIndex = -1;
title = '';
content='';
activePost: Post;
images: string[] =["../assets/img/damwon.jpg",
"../assets/img/FPX.jpg",
"../assets/img/2015skt.webp",
"../assets/img/2017SSG.webp",
"../assets/img/2014SSW.webp",
"../assets/img/TPA.webp",
"../assets/img/Fnatic.webp"]
backgroundImage: string = '';
constructor(private PostService: PostService,
private route: Router) { }
ngOnInit() {
let ran = Math.floor(Math.random()*6);
console.log(ran, Math.random()*100)
this.backgroundImage = this.images[ran];
this.retrieveposts();
}
refreshList(): void {
this.currentpost = undefined;
this.currentIndex = -1;
this.retrieveposts();
}
retrieveposts(): void {
this.PostService.getAll().snapshotChanges().pipe(
map(changes =>
changes.map(c =>
({ id: c.payload.doc.id, ...c.payload.doc.data() })
)
)
).subscribe(data => {
this.posts = data;
});
}
setActivepost(post: Post, index: number): void {
this.currentpost = post;
this.currentIndex = index;
console.log("Post:", post, "Index:", index);
this.activePost = this.currentpost
this.route.navigate(['/Read/'])
}
}
Child ts file (post-display component)
import { Component, OnInit, Input, OnChanges, Output, EventEmitter } from '#angular/core';
import { Post } from 'src/app/models/post.model';
import { PostService } from 'src/app/services/post.service';
import { HomepageComponent } from 'src/app/homepage/homepage.component';
#Component({
selector: 'app-post-display',
templateUrl: './post-display.component.html',
styleUrls: ['./post-display.component.scss']
})
export class PostDisplayComponent implements OnInit {
#Input() activePost: Post;
#Output() refreshList: EventEmitter<any> = new EventEmitter();
currentPost: Post = {
title: '',
description: '',
category:'',
published: false,
content: ''
};
message = '';
constructor(private PostService: PostService) { }
ngOnInit(): void {
console.log(this.activePost)
}
}
Child HTML:
<div class="container" style="padding-top: 200px;">
<div class="post">
ACTIVE POST HERE:
{{activePost}}
</div>
Looking at the console, the child component always returns undefined for activePost. I'm not sure if this is because I dont have anything in the parent html code for the child to look at? I feel like I should just be able to do this in the .ts file.
Help would be appreciated. Let me know if there are other project docs I should share as well.
Edit, added parent html:
<header class="header" [ngStyle]="{'background-image': 'url(' + backgroundImage + ')'}">
<div class="content">
<h1 class="heading">
<span class="small">Samsite:</span>
Stat
<span class="no-fill">check</span>
</h1>
<!--write a blog-->
</div>
</header>
<section class="blogs-section">
<div class="blog-card"
*ngFor="let post of posts; let i = index"
>
<h1>Title: {{ post.title }}</h1>
<h2> Category: {{ post.category }}</h2>
<p class="blog-overview"> Preview: {{ post.description }}</p>
<div class="btn" (click)="setActivepost(post, i)">Read!</div>
</div>
</section>

How do I reload data after deletion?

I have created some posts in my app as html cards. I have a component called PostList, where I am displaying all these cards. On every card I have a delete button to delete that specific card, which works, but after I delete one card, it doesn't disappear from my post list until I manually refresh the page. This is my card:
<div class="card-body">
<h5 class="card-title cut_text">{{post.title}}</h5>
<p class="card-text cut_text" style="text-align: left;">
{{post.text}}
</p>
<span>Read more</span>
<button *appHasRole='["Admin"]' class="ml-5" (click)="deletePost(post.id)" type="button" style="box-shadow: 1px 1px grey;"><em class="fa fa-trash"></em></button>
</div>
And this is the delete function:
#Component({
selector: 'app-post-card',
templateUrl: './post-card.component.html',
styleUrls: ['./post-card.component.css']
})
export class PostCardComponent implements OnInit {
#Input() post: Post;
posts: Post[];
model: any = {};
user: User;
postId: number;
constructor(private postService: PostsService, private toastr: ToastrService,
private route: ActivatedRoute, public accountService: AccountService) {}
ngOnInit(): void {
this.route.params.subscribe((params) => {
console.log(params);
this.postId = params['id'];
});
}
deletePost(id: number) {
this.postService.deletePost(id).subscribe(() =>{
this.toastr.success('Deleted');
}, error => {
console.log(error);
this.toastr.error(error.error);
});
}
}
This is the html of the post list:
<div class=" container mt-3" >
<span *ngFor="let post of posts">
<app-post-card [post]="post" class="item" ></app-post-card>
</span>
</div>
And this is the method to load the posts:
export class PostListComponent implements OnInit {
posts: Post[];
post: Post;
pagination: Pagination;
postParams: PostParams = new PostParams();
constructor(private postService: PostsService) { }
ngOnInit(): void {
this.loadPosts();
}
loadPosts() {
this.postService.getPosts(this.postParams).subscribe(response => {
this.posts = response.result;
this.pagination = response.pagination;
});
}
}
I have tried calling the loadPosts() method after deleting a card, althought it is not very efficient, but it doesn't work, I still have to refresh the page. What can I do so that it automatically disappears after I am deleting it?
You could use #Output from the child component to send the id that was deleted and remove the element corresponding to this id from the posts variable in parent component.
post-card.component.ts
import { Component, Input, Output, EventEmitter } from '#angular/core';
#Component({
selector: 'app-post-card',
templateUrl: './post-card.component.html',
styleUrls: ['./post-card.component.css']
})
export class PostCardComponent implements OnInit {
#Input() post: Post;
#Output() postRemoved = new EventEmitter(); // <-- custom event
posts: Post[];
model: any = {};
user: User;
postId: number;
constructor(private postService: PostsService, private toastr: ToastrService,
private route: ActivatedRoute, public accountService: AccountService) {}
ngOnInit(): void {
this.route.params.subscribe((params) => {
console.log(params);
this.postId = params['id'];
});
}
deletePost(id: number) {
this.postService.deletePost(id).subscribe(() =>{
this.toastr.success('Deleted');
this.postRemoved.emit(id); // <-- emit the id in the event
}, error => {
console.log(error);
this.toastr.error(error.error);
});
}
}
post-list.component.html
<div class=" container mt-3" >
<span *ngFor="let post of posts">
<app-post-card (postRemoved)="onPostRemoved($event)" [post]="post" class="item" ></app-post-card>
</span>
</div>
post-list.component.ts
onPostRemoved(id: any) {
this.posts = JSON.parse(JSON.stringify( // <-- assign a deep clone
this.posts.filter(post => post.id !== id)
));
}

#viewChild and #ViewChildern gives undefined

I'm working on Angular 9 and want to access an input field after clicking on a button. right now it gives me undefined. I have tried #ViewChild and #viewChildern because I'm using ngIf.
Template.html file
<div class="search-input" #searchDiv *ngIf="serachActive">
<input
#searched
autofocus
type="text"
class="serach-term"
placeholder="Search"
[(ngModel)]="searchTerms"
(ngModelChange)="applySearch()"
/>
<button (click)="toggleSearch(!serachActive)">
<span class="material-icons"> search </span>
</button>
<ul class="search-list">
<li *ngFor="let result of results">
<a [routerLink]="['/', 'video', 'details', result._id]">{{
result.title ? result.title : ''
}}</a>
</li>
</ul>
</div>
Template.ts file
import { Component, OnInit,AfterViewInit,ElementRef,ViewChild,ViewChildren } from '#angular/core';
import { UserService } from '../../../user.service';
import { VideoService } from '../../../services/video.service';
import { Subject } from 'rxjs';
import { distinctUntilChanged, debounceTime } from 'rxjs/operators';
import { Router } from '#angular/router';
#Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.css'],
})
export class HeaderComponent implements OnInit,AfterViewInit{
serachActive: boolean = false;
#ViewChildren('searched') searchElement: ElementRef;
#ViewChildren("searched") input: ElementRef;
user;
subject = new Subject<string>();
results = [];
searchTerms;
loggedIn: Boolean = false;
constructor(
private userService: UserService,
private videoService: VideoService,
private router: Router
) {
this.user = this.userService.getUser();
this.loggedIn = this.userService.isAuthenticated();
}
ngOnInit() {
console.log('on init', this.input); //undefined
this.subject
.pipe(debounceTime(400), distinctUntilChanged())
.subscribe((value) => {
this.router.navigate(['search'], { queryParams: { term: value } });
});
}
ngAfterViewInit() {
console.log('on after', this.input); //undefined
}
toggleSearch(toggledata) {
this.serachActive = toggledata;
this.results = [];
this.searchTerms = '';
console.log(this.input) //undefined
console.log(this.searchElement.nativeElement) //undefined
}
applySearch() {
const searchText = this.searchTerms;
this.subject.next(searchText);
this.searchElement.nativeElement.focus(); //undefined
}
menuButtonClick(button){
if(button === "history"){
this.router.navigate(['history'])
}
}
}
Use ViewChild since you're only searching for 1 element ID.
If adding { static: true } or { static: false } in your ViewChild options doesn't work as what is stipulated on Angular Static Query Migration Documentation
Use ChangeDetectorRef instead:
#Component({...})
export class AppComponent {
#ViewChild('searchInput') input: ElementRef;
isShow: boolean = false;
constructor(private cdr: ChangeDetectorRef) {}
toggle(): void {
this.isShow = !this.isShow;
this.cdr.detectChanges(); // Detects changes which this.isShow is responsible on showing / hiding
// the element you're referencing to in ViewChild
if (this.isShow) // If element is shown, console the referenced element
console.log(this.input);
}
}
Have created a Stackblitz Demo for your reference

How can I show data in an Angular component in Angular 10?

I'm starting with Angular 10 and I want to put the current user in the profile.component.html and the navbar in app.component.html. Here is the code.
users.ts
export interface User {
username : string
password: string
edad: number
fechaNacimiento: string
createdAt?: string
updatedAt?: string
id?:number
}
login.component.ts
import { Component, OnInit } from '#angular/core';
import { NgForm } from '#angular/forms';
import { ActivatedRoute, Router } from '#angular/router';
import { UsersService } from 'src/app/services/users.service';
#Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
constructor(
public usersServices: UsersService,
private router: Router
) { }
ngOnInit(): void {
}
login(form: NgForm){
this.usersServices.login(form.value).subscribe(
res => {
console.log(res);
localStorage.setItem('token',res['token']);
this.router.navigate(['/profile',form.controls['username'].value],{
state:{username:form.controls['username']}
});
},
err => {
console.log(err)
}
)
}
}
profile.component.ts
import { Component, OnInit } from '#angular/core';
import { UsersService } from '../../services/users.service';
import { NgForm } from '#angular/forms';
import { User } from 'src/app/models/users';
import { ActivatedRoute } from '#angular/router';
#Component({
selector: 'app-profile',
templateUrl: './profile.component.html',
styleUrls: ['./profile.component.css']
})
export class ProfileComponent implements OnInit {
constructor(public usersService: UsersService,private route: ActivatedRoute) {
this.route.params.subscribe(username => {
console.log(username);
})
}
ngOnInit(): void {
this.getUsers();
}
getUsers(){
this.usersService.getUsers().subscribe(
res => {
this.usersService.user = res
},
err => console.log(err)
)
}
deleteUser(id:number){
if(confirm('Are you sure you want to delete it?')){
this.usersService.deleteUser(id).subscribe(
(res) => {
this.getUsers();
},
(err) => console.log(err)
);
}
}
updateUser(form: NgForm){
this.usersService.editUser(form.value).subscribe(
res => console.log(res),
err => console.log(err)
);
}
}
<div class="col-md-8">
<table class="table table-striped">
<thead>
<tr>
<th>Username</th>
<th>Age</th>
<th>Birthdate</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let user of usersService.user">
<td>{{user.username}}</td>
<td>{{user.edad}}</td>
<td>{{user.fechaNacimiento}}</td>
<td>
<button class="btn btn-secondary btn-sm" data-toggle="modal" data-target="#staticBackdrop">
<i class="material-icons">edit</i>
</button>
<button class="btn btn-danger btn-sm" (click)="deleteUser(user.id)">
<i class="material-icons">delete</i>
</button>
</td>
</tbody>
</table>
</div>
app.component.html
<nav class="navbar navbar-dark bg-dark">
<div class="container">
<a class="navbar-brand" href="#">MEAN Users</a>
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" routerLink="/profile" routerLinkActive = "active">Profile</a>
</li>
</ul>
<ul class="navbar-nav ml-auto">
<ng-container *ngIf="!usersService.loggedIn(); else loggedIn">
<li class="nav-item">
<a class="nav-link" routerLink="/register" routerLinkActive = "active">Signup</a>
</li>
<li class="nav-item">
<a class="nav-link" routerLink="/login" routerLinkActive = "active">Signin</a>
</li>
</ng-container>
<ng-template #loggedIn>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" data-toggle="dropdown" role="button" style="cursor: pointer;"></a>
<div class="dropdown-menu">
<a class="dropdown-item" (click)="usersService.logout()">Logout</a>
</div>
</li>
</ng-template>
</ul>
</div>
</nav>
<div class="container p-5">
<router-outlet></router-outlet>
</div>
I want to put a single user in the navbar from app.component.html and profile.component.html but i don't know how to do it.
Beforehand thank you very much.
The problem is not much clear to me, but I think this may help you.
It is better to create an authentication service. The authentication service is used to login & log out, it notifies other components when the user logs in & out, and allows access the currently logged in user.
RxJS Subjects and Observables are used to store the current user object and notify other components when the user logs in and out of the app. Angular components can subscribe() to the public currentUser: Observable property to be notified of changes, and notifications are sent when the this.currentUserSubject.next() method is called in the login() and logout() methods, passing the argument to each subscriber.
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { BehaviorSubject, Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { User } from '#app/_models';
#Injectable({ providedIn: 'root' })
export class AuthenticationService {
private currentUserSubject: BehaviorSubject<User>;
public currentUser: Observable<User>;
apiUrl: string;
constructor(private http: HttpClient) {
this.currentUserSubject = new BehaviorSubject<User>(JSON.parse(localStorage.getItem('currentUser')));
this.currentUser = this.currentUserSubject.asObservable();
}
public get currentUserValue(): User {
return this.currentUserSubject.value;
}
login(username: string, password: string) {
return this.http.post<any>(`${this.apiUrl}/users/authenticate`, { username, password })
.pipe(map(user => {
// store user details and jwt token in local storage to keep user logged in between page refreshes
localStorage.setItem('currentUser', JSON.stringify(user));
this.currentUserSubject.next(user);
return user;
}));
}
logout() {
// remove user from local storage to log user out
localStorage.removeItem('currentUser');
this.currentUserSubject.next(null);
}
}
you can use the current user like this
currentUser: User;
constructor(
private authenticationService: AuthenticationService
) {
this.authenticationService.currentUser.subscribe(x => this.currentUser = x);
}
if the current user is undefined, you can navigate to again login page. if not you can display the current user.

Currently logged in user won’t display on the navbar until I manually refresh the browser

The last previous account name is displayed. It's only when I refresh the browser the displayed name changes to the current logged in account.
below is the Auth service.
import { HttpClient } from '#angular/common/http';
import { Injectable } from '#angular/core';
import { environment } from 'src/environments/environment';
import { map } from 'rxjs/operators';
import { DefaultUrlSerializer } from '#angular/router';
import { JwtHelperService } from '#auth0/angular-jwt';
import { Observable } from 'rxjs';
import { yearsPerPage } from '#angular/material/datepicker';
#Injectable({
providedIn: 'root'
})
export class AuthService {
baseUrl = environment.apiUrl + 'auth/';
decodedToken: any;
jwtHelper = new JwtHelperService();
constructor(private http: HttpClient) { }
login(model: any) {
return this.http.post(this.baseUrl + 'login', model)
.pipe(
map((response: any) => {
const user = response;
if (user) {
localStorage.setItem('token', user.token);
localStorage.setItem('user', JSON.stringify(user.user));
this.decodedToken = this.jwtHelper.decodeToken(user.token);
localStorage.setItem('role', JSON.stringify(this.decodedToken.role));
}
})
);
}
register(model: any) {
return this.http.post(this.baseUrl + 'register', model, { responseType: 'text' });
}
loggedIn() {
const token = localStorage.getItem('token');
return !this.jwtHelper.isTokenExpired(token);
window.location.reload();
}
role() {
return localStorage.getItem('role');
}
}
I’m getting the logged in details from the local storage and storing the details into a variable called userDisplayName in the navbar component. As you can see below the code is in ngONInit method.
“this.userDisplayName = JSON.parse (localStorage.getItem('user'));”
import { AddTaskComponent } from './../addTask/addTask.component';
import { AuthService } from './../_services/auth.service';
import { Component, OnInit } from '#angular/core';
import { FormGroup, FormControl, Validators } from '#angular/forms';
import { MatDialog } from '#angular/material/dialog';
import { UpdateTaskComponent } from '../updateTask/updateTask.component';
import { Router } from '#angular/router';
import { UserMemberService } from '../_services/userMember.service';
import { StateStorageService } from '../_services/stateStorage.service';
#Component({
selector: 'app-navigation-bar',
templateUrl: './navigationBar.component.html',
styleUrls: ['./navigationBar.component.css']
})
export class NavigationBarComponent implements OnInit {
model: any = {};
loginReactiveForm: FormGroup;
role;
users: any[];
userAuthorised: boolean;
searchTask: FormControl;
Username: string;
userDisplayName;
constructor(
private authService: AuthService,
public dialog: MatDialog,
private router: Router,
private userMemberService: UserMemberService,
private stateStorageService: StateStorageService) { }
ngOnInit() {
this.initForm();
this.isUserAdmin();
// this.userDisplayName = this.authService.login(this.model);
this.userDisplayName = JSON.parse (localStorage.getItem('user'));
console.log(this.role);
}
login() {
this.model.username = this.loginReactiveForm.value.username;
this.model.password = this.loginReactiveForm.value.password;
this.authService.login(this.model).subscribe(next => {
this.loadUsers();
this.router.navigateByUrl('/CalendarView');
this.isUserAdmin();
}, error => {
console.log('failed to login');
});
}
isUserAdmin() {
// get users role
this.role = JSON.parse(localStorage.getItem('role'));
console.log('this is role = ' + this.role);
// if user is not an Admin
if (this.role !== 'Admin') {
this.userAuthorised = false;
console.log('value of auth is = ' + this.userAuthorised );
} // if user is an Admin
else {
// list of users for the drop down
this.userAuthorised = true;
console.log('value of auth is = ' + this.userAuthorised );
}
}
loadUsers() {
this.userMemberService.getUsers().subscribe((data) => {
this.users = data;
this.stateStorageService.setUserMemberStorage(this.users);
}, error => {
console.log(error);
});
}
initForm() {
this.loginReactiveForm = new FormGroup({
username: new FormControl(),
password: new FormControl()
});
this.searchTask = new FormControl();
}
// has the user logged in
loggedIn() {
return this.authService.loggedIn();
}
loggedOut() {
const token = localStorage.removeItem('token');
const username = localStorage.removeItem('user');
const userId = localStorage.removeItem('role');
localStorage.removeItem('user');
}
}
Below is the html
<nav class="navbar navbar-expand-md navbar-dark bg-dark">
<ul *ngIf="!loggedIn()" class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link">
<span class="sr-only"></span></a>
</li>
</ul>
<form *ngIf="!loggedIn()" class="form-inline my-2 my-lg-0" [formGroup]="loginReactiveForm"
(ngSubmit)="login()">
<input formControlName="username" class="form-control mr-sm-2"
type="text" placeholder="Username" aria-label="username">
<input formControlName="password" class="form-control mr-sm-2"
type="password" placeholder="Password" autocomplete="off" aria-label="password">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Login</button>
</form>
<div *ngIf="loggedIn()" class="username" style="position:relative; left:70%; color: white ;" >Username: {{userDisplayName.username}}</div>
<div style="position:relative; left:85%">
<button *ngIf="loggedIn()" class="btn btn-outline-success float-right"
type="submit" (click)="loggedOut()" [routerLink]="['/login']">Log Out</button>
</div>
</nav>
Why is is that the loggedin user is only displayed once the browser has been refreshed?
I'm currently logged in as “Matt Briggs” but it shows “Sallyjones” on the navbar in the image.
Link to the image is here
Problem
The problem in your code is that you only set userDisplayName once in ngOnInit. NgOnInit is only called once when the component is initialised. So this is why you need to refresh to see the new user from localstorage.
There's no other place where you change or update userDisplayName...
Solution
I think your code could use a little refactoring to make it work like you expect. You're putting to much logic in your component code.
Save your decodedToken in a currentUser subject which is exposed as an observable ==> By doing this, you can subscribe to this observabel in your component's ngOnInit function. This way every change will be shown in your component too.
This is a tutorial which gives a complete overview of how you can implement authentication in Angular. Give it a good read and try this out in your code.
https://jasonwatmore.com/post/2020/07/09/angular-10-jwt-authentication-example-tutorial#authentication-service-ts
this sounds like a change detection problem. Can you use a Subject to store the userDisplayName?
e.g.
export class NavigationBarComponent implements OnInit {
...
userDisplayName = new Subject<{username: string}>;
...
const _u = JSON.parse(localStorage.getItem('user'));
this.userDisplayName.next(_u);
then in your template
<div *ngIf="loggedIn()"
class="username"
style="position:relative; left:70%; color: white ;" >
Username: {{(userDisplayName | aasync)?.username}}
</div>
Using a subject will cause ng to redraw the ui when the value of userDisplayName changes.
I am guessing that ng is drawing the dom on init, when there is an old value in userDisplayName and doesn't know the value has changed. Using a subscribable will fix that.
you can directly call it from your server to html page
get loggedInUser(): any {
const uname = localStorage.getItem('uname');
return uname;
}
In your html page
<li><a *ngIf="auth.isLoggedIncheck"><span class="glyphicon glyphicon-log-in"></span> Welcome{{auth.loggedInUser| uppercase}} </a> </li>