I'm writing web-app in Angular 8.
I have header and login page. I want to update my header after login to show information about current logged user. I'm using BehaviourSubject to do this but it doesn't work.
It's my auth service where is BehaviorSubject
@Injectable()
export class AuthService {
private readonly GRANT_TYPE = 'password';
logged: BehaviorSubject<UserDataModel> = new BehaviorSubject<UserDataModel>(null);
//private auth$: Observable<Auth>;
constructor(private httpClient: HttpClient, private router: Router) { }
login(credentials: CredentialsModel) {
this.httpClient.post('http://localhost:8080/api/oauth/token',
this.prepareParams(credentials),
{ headers: this.prepareHeaders() })
.subscribe(token => {
let userData = new UserDataModel();
userData.token = token['access_token'];
this.getUserInfo(userData);
});
//this.saveAuth();
}
autoLogin() {
const userData = JSON.parse(localStorage.getItem('user'));
if (!userData) {
return;
}
if (userData.token) {
this.logged.next(userData);
}
}
private prepareHeaders(): HttpHeaders {
let headers = new HttpHeaders();
headers = headers.append('Authorization', 'Basic ' + btoa('frontendClientId:frontendClientSecret'));
headers = headers.append('Content-Type', 'application/x-www-form-urlencoded');
return headers;
}
private prepareParams(credentials: CredentialsModel) {
let params = new HttpParams();
params = params.append('username', credentials.username);
params = params.append('password', credentials.password);
params = params.append('grant_type', this.GRANT_TYPE);
return params;
}
private getUserInfo(userData: UserDataModel) {
this.httpClient.get('http://localhost:8080/api/user/user/current',
{headers: new HttpHeaders().append('Authorization', 'Bearer ' + userData.token)})
.subscribe(data => {
userData.email = data['name'];
userData.role = data['authorities'][0]['authority'];
this.saveUser(userData);
this.logged.next(userData);
this.router.navigate(['../']);
})
}
private saveUser(userData: UserDataModel) {
localStorage.setItem('user', JSON.stringify(userData))
}
}
There is my header component where I subscribe BehaviorSubject from auth service
@Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit, OnDestroy, DoCheck {
loggedIn: boolean = false;
username: string ='';
private subscriptions: Subscription[] = [];
constructor(private authService: AuthService) { }
ngOnInit() {
this.subscriptions.push(this.authService.logged.subscribe(this.onLogged));
}
ngDoCheck(): void {
this.authService.autoLogin();
}
onLogout() {
this.loggedIn = false;
}
onLogged(userData: UserDataModel) {
if(userData) {
this.loggedIn = true;
this.username = userData.email;
}
}
ngOnDestroy(): void {
this.subscriptions.forEach(sub => sub.unsubscribe());
}
}
Some html code where it doesn't update after login:
<div class="header-actions" *ngIf="!loggedIn">
<a routerLink="/login" class="nav-link nav-icon-text">
<clr-icon shape="user"></clr-icon>
<span class="nav-text">Zaloguj się</span>
</a>
<a href="" class="nav-link nav-icon-text">
<clr-icon shape="plus"></clr-icon>
<span class="nav-text">Zarejestruj się</span>
</a>
</div>
<div class="header-actions" *ngIf="loggedIn">
<clr-dropdown>
<button class="nav-text" clrDropdownTrigger>
{{username}}
<clr-icon shape="caret down"></clr-icon>
</button>
<clr-dropdown-menu *clrIfOpen clrPosition="bottom-right">
<a routerLink="#" clrDropdownItem>Profil</a>
<a routerLink="#" clrDropdownItem (click)="onLogout()">Wyloguj</a>
</clr-dropdown-menu>
</clr-dropdown>
</div>
In the login component I invoke method 'login' from auth.service and it's work, it's correctly navigate to the dashboard but without updated header.
Do you know what I am doing wrong?