Reputation: 70
So I am currently following some course. I have simple login form inside the nav bar
<nav class="navbar navbar-expand-md navbar-dark fixed-top bg-primary">
<div class="container">
<a class="navbar-brand" routerLink='/' routerLinkActive='active' >Dating app</a>
<ul class="navbar-nav mr-auto" >
<ng-container *ngIf="accountService.currentUser$ | async">
<li class="nav-item">
<a class="nav-link" routerLink="/members" routerLinkActive='active'>Matches</a>
</li>
<li class="nav-item">
<a class="nav-link" routerLink="/lists" routerLinkActive='active'>Lists</a>
</li>
<li class="nav-item">
<a class="nav-link" routerLink="/messages" routerLinkActive='active'>Messages</a>
</li>
</ng-container>
</ul>
<div class="dropdown" *ngIf="(accountService.currentUser$ | async) as user" dropdown>
<a class="dropdown-toggle text-light" dropdownToggle>Welcome {{user.username | titlecase}}</a>
<div class="dropdown-menu mt-3" *bsDropdownMenu>
<a class="dropdown-item">Edit profile</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" (click)="logout()">Logout</a>
</div>
</div>
<form *ngIf="(accountService.currentUser$ | async) === null" #loginForm="ngForm" class="form-inline mt-2 mt-md-0" (ngSubmit)="login()"
autocomplete="off">
<input
name="username"
[(ngModel)]="model.username"
class="form-control mr-sm-2"
type="text"
placeholder="Username">
<input
name="password"
[(ngModel)]="model.password"
class="form-control mr-sm-2"
type="password"
placeholder="Password">
<button class="btn btn-success my-2 my-sm-0" type="submit">Login</button>
</form>
</div>
</nav>
I want to show Welcome {username} when the client is logged in, and login form when nobody is logged in. The thing is when I start the angular app, it is displaying this
instead of this:
Localstorage is empty when I start the app so I literaly have no idea why is this happening. The service I am using looks like this:
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { ReplaySubject } from 'rxjs';
import { map } from 'rxjs/operators'
import { User } from '../_models/User';
@Injectable({
providedIn: 'root'
})
export class AccountService {
baseUrl = "https://localhost:5001/api/";
private currentUserSource = new ReplaySubject<User>(1);
currentUser$ = this.currentUserSource.asObservable();
constructor(private http: HttpClient) { }
login(model:User)
{
return this.http.post<User>(this.baseUrl + 'account/login',model).pipe(
map((response: User) => {
const user = response;
if(user)
{
localStorage.setItem('user',JSON.stringify(user));
this.currentUserSource.next(user);
}
})
)
}
register(model:User)
{
return this.http.post<User>(this.baseUrl+'account/register',model).pipe(
map((user: User) => {
if(user)
{
localStorage.setItem('user',JSON.stringify(user));
this.currentUserSource.next(user);
}
})
)
}
setCurrentUser(user: User){
this.currentUserSource.next(user);
}
logout()
{
localStorage.removeItem('user');
this.currentUserSource.next(null!);
}
}
The only difference I can spot between my code and the code in tutorial is
this.currentUserSource.next(null!);
and in tutorial it is
this.currentUserSource.next(null);
But when I use null without !, it gives me error and I could not fix it.
I know this might be something silly but I could not get around it
Upvotes: 1
Views: 531
Reputation: 2632
In your component, you check if the current user is truthy:
<div class="dropdown" *ngIf="(accountService.currentUser$ | async) as user" dropdown>
The problem is that when the sessionStorage
is empty, you put an empty object ({}
) as the current user. And, since objects are always truthy, the welcome message appears:
// src/app/app.component.ts:27
const user: User = JSON.parse(localStorage.getItem('user') || '{}');
this.accountService.setCurrentUser(user);
In this case, you should set the current user to null
:
// src/app/app.component.ts:27
const user: User | null = JSON.parse(localStorage.getItem('user') || null);
And in the service change the types to allow this:
private currentUserSource = new ReplaySubject<User|null>(1);
// ...
setCurrentUser(user: User | null){
// ...
Upvotes: 1
Reputation: 3022
Try to change ReplaySubject for BehaviorSubject :
private currentUserSource = new BehaviorSubject<User|null>(null);
and
this.currentUserSource.next(null);
Upvotes: 1