Looking to share a value between 2 Angular2 components?
The code for my App component is:
<app-header></app-header>
<router-outlet></router-outlet>
<app-footer></app-footer>
The typescript code for my login component loaded in
<router-outlet></router-outlet>
:
import { Component, OnInit } from '@angular/core';
import { MatInput } from '@angular/material';
import { Router } from '@angular/router';
import { LoginService } from '../../services/login.service';
import { User } from '../../models/user';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
providers: [ LoginService ],
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
public user = new User('', '', new Array<string>());
public errorMsg = '';
public isLoading = false;
constructor(
private loginService: LoginService,
private router: Router
) { }
ngOnInit() {
if (this.loginService.getCurrentUser() !== null) {
this.router.navigate(['home']);
}
}
login() {
this.isLoading = true;
const obs = this.loginService.login(this.user);
obs.subscribe(
res => {
if (res !== true) {
this.errorMsg = 'Incorrect Username / Password';
this.loginService.loginStatusChange(false);
} else {
this.loginService.loginStatusChange(true);
}
},
err => {
this.isLoading = false;
this.errorMsg = err._body;
this.loginService.loginStatusChange(false);
},
() => {
this.isLoading = false;
}
);
obs.connect();
}
}
The typescript code for my header component:
import { Component, OnInit } from '@angular/core';
import { User } from '../../models/user';
import { LoginService } from '../../services/login.service';
@Component({
selector: 'app-header',
templateUrl: './header.component.html',
providers: [ LoginService ],
styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit {
public currentUser: string;
constructor(private loginService: LoginService) { }
ngOnInit() {
const currentUser = this.loginService.getCurrentUser();
if (currentUser !== null) {
this.currentUser = currentUser.username;
}
this.loginService.loginObservable
.map((status) => {
if (status) {
return this.loginService.getCurrentUser();
}
return null;
}
)
.subscribe((user) => {
const thisUser = this.loginService.getCurrentUser();
if (thisUser !== null) {
this.currentUser = thisUser.username;
}
});
}
logout() {
this.loginService.logout();
this.loginService.loginStatusChange(false);
}
}
The view for my header component:
<div id="wrapper">
<section>
<div id="topHeader">
<div class="oLogo">
<img id="OLogoImg" src="../../assets/images/Luceco-O-Logo-Transparent.png" alt="o-logo" height="20" />
</div>
</div>
</section>
</div>
<div class="container body-content">
<div id="header">
<div class="pageWrap">
<a id="logo" >
<img id="logoImg" src="../../assets/images/Luceco-Logo-Transparent.png" alt="logo" height="28" />
</a>
<ul id="menu">
<li id="home-menu" class="top-level home-menu">
<a href="#">Home</a>
</li>
<--DISPLAYS THE FOLLOWING COMPONENT AFTER LOGIN -->
<li *ngIf="currentUser != null" id="logout-menu" class="top-level logout-menu">
<a href="#" (click)="logout()">Log Out</a>
</li>
</ul>
</div>
</div>
LoginService:
import { Injectable } from '@angular/core';
import { Http, Headers, RequestOptions, Response } from '@angular/http';
import { Router } from '@angular/router';
import 'rxjs/rx';
import { ConnectableObservable } from 'rxjs/rx';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Observable } from 'rxjs/Observable';
import { User } from '../models/user';
@Injectable()
export class LoginService {
private authApiUrl = 'http://192.168.1.201/ForkliftHelperAPI/api/Auth';
private loginBehaviourSubject = new BehaviorSubject<boolean>(false);
public loginObservable = this.loginBehaviourSubject.asObservable();
constructor(private router: Router,
private _http: Http) { }
loginStatusChange(isLoggedIn: boolean) {
this.loginBehaviourSubject.next(isLoggedIn);
}
login(user: User): ConnectableObservable<any> {
let result: User;
const body = JSON.stringify(user);
const headers = new Headers({
'Content-Type': 'application/json'
});
const options = new RequestOptions({
headers: headers
});
const obsResponse = this._http.post(this.authApiUrl, body, options)
.map(res => res.json())
.publish();
obsResponse.subscribe(
(res: User) => {
result = res;
if (result) {
user.securityGroups = result.securityGroups;
sessionStorage.setItem('user', JSON.stringify(user));
this.router.navigate(['home']);
}
},
err => console.log(err)
);
return obsResponse;
}
logout() {
sessionStorage.removeItem('user');
this.router.navigate(['login']);
}
getCurrentUser() {
const storedUser = JSON.parse(sessionStorage.getItem('user'));
if (!storedUser) {
return null;
}
return new User(storedUser.username, storedUser.password, storedUser.securityGroups);
}
isLoggedIn() {
if (this.getCurrentUser() === null) {
this.router.navigate(['login']);
}
}
}
Struggling with updating the header component after a redirect? Try refreshing the header manually after redirection. Tried using services, @Input(), and @Output() without success? Seeking advice on proper implementation.
Issue arises when redirects occur, only components within
<router-outlet></router-outlet>
are refreshed while the header and footer remain static. Considering placing the header and footer components in every other component for correct display, although not ideal.
Your guidance would be greatly valued.