I am encountering an unusual issue with my Angular code involving a login page that interacts with an API.
login.component.ts:
export class LoginComponent implements OnInit {
formData;
constructor(private usersService: UsersService, private router: Router) { }
ngOnInit() {
this.formData = new FormGroup({
login: new FormControl('', [Validators.required]),
password: new FormControl('', [Validators.required])
});
}
onClickSubmit(data) {
this.usersService.login(data).subscribe((response) => {
const token = response.token;
const userLogin = response.user.userLogin;
localStorage.setItem('token', token);
localStorage.setItem('login', userLogin);
this.router.navigate(['/home']);
});
}
}
login.component.html:
<div class="card mb-3">
<div class="card-header">
Login
</div>
<div class="card-body">
<form [formGroup]="formData" (ngSubmit)="onClickSubmit(formData.value)" novalidate>
<div class="form-group">
<label for="inputLogin">Login</label>
<input type="text" class="form-control" id="inputLogin" name="login" placeholder="Login" formControlName="login">
<span *ngIf="(login.dirty || login.touched) && login.invalid && login.errors.required" class="error">Login is required</span>
</div>
<div class="form-group">
<label for="inputPassword">Password</label>
<input type="password" class="form-control" id="inputPassword" name="password" placeholder="Password" formControlName="password">
<span *ngIf="(password.dirty || password.touched) && password.invalid && password.errors.required" class="error">Login is required</span>
</div>
<button type="submit" class="btn btn-primary" [disabled]="!formData.valid">Sign in</button>
</form>
</div>
<p class="card-text login-text"><small class="text-muted">Don't have any account? <a routerLink="/register">Register</a></small></p>
</div>
I observed that this.router.navigate()
executes before localStorage.setIem
.
users.service.ts:
export class UsersService {
private apiUrl = 'https://localhost:63939/api/v1/';
private registerUrl = this.apiUrl + 'identity/register';
private loginUrl = this.apiUrl + 'identity/login';
constructor(private httpClient: HttpClient) { }
register(user: User): Observable<AuthResponse> {
return this.httpClient.post<AuthResponse>(this.registerUrl, user);
}
login(user: LoginRequest): Observable<AuthResponse> {
return this.httpClient.post<AuthResponse>(this.loginUrl, user);
}
}
menu.component.ts:
export class MenuComponent implements OnInit {
showLoginLink = true;
userLogin;
constructor() { }
ngOnInit() {
this.userLogin = localStorage.getItem('login');
if (this.userLogin !== null) {
this.showLoginLink = false;
}
}
}
menu.component.html
<li class="nav-item" *ngIf="showLoginLink">
<a class="nav-link" routerLink="/register">Login / Register</a>
</li>
<li class="nav-item" *ngIf="userLogin">
<a class="nav-link" routerLink="/register">{{userLogin}}</a>
</li>
After the navigation, the menu displays without the localStorage data causing *ngIf="userLogin"
to not work. However, refreshing the page populates the values and activates the menu correctly. Is there a way to update the menu dynamically without a page refresh?
(I prefer an explanation over a ready-made solution but I'm open to suggestions ^-^)
EDIT: Additional code provided based on comments :) Will make further edits if necessary