Reputation: 1687
Hi all I am beginner in angular2. I am creating a small demo application for learning purpose.
app.component.ts
template: `
<header-content></header-content>
<main-content></main-content>
<footer-content></footer-content>
`
In my header I have a navigation section like home, login etc.
Main-content-template structure
<div class="container main">
<div class="row">
<router-outlet></router-outlet>
</div>
</div>
As you can see I have placed the router-outlet for the header and footer section links inside main-content.
By defalut I am at Login page /login.
I have a separate component for every links.
What I want is when user clicks on submit button on login page I am redirecting him to some other xyz page.But along with that I want my Login link to get hide from the header nav and display a user name.
<li *ngIf='!isUserLoggedIn'><a routerLink="/login">Login</a></li>
<li *ngIf='isUserLoggedIn'><a>Welcome {{user}}</a></li>
HeaderComponent.ts
@Component({
moduleId : module.id,
selector : 'header-content',
templateUrl: 'Header.html',
providers: [LoginService]
})
export class HeaderComponent implements OnInit {
isUserLoggedIn = false;
user : string;
constructor(private loginService: LoginService) { }
getUserName() :void {
this.user = this.loginService.getUserName(); // reading data from localstorage on page refresh
if(this.user) {
this.isUserLoggedIn = true;
}
}
ngOnInit(): void {
this.getUserName();
// Will fire everytime other component use the setter this.loginService.setLogged()
this.loginService.getLogged().subscribe((logged) => {
console.log('Welcome===>', logged);
});
}
}
Login-Service.ts
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';
import { Observable } from 'rxjs/Observable';
@Injectable()
export class LoginService {
username : string;
private logged: boolean;
private subject: Subject<boolean> = new Subject<boolean>();
setLogged(logged: boolean): void {
this.logged = logged;
this.subject.next(logged);
}
getLogged() {
return this.subject.asObservable();
}
constructor() {
if(localStorage.getItem('userName')){
this.username = localStorage.getItem('userName');
}
}
getUserName():string {
if(this.username)
return this.username;
}
}
I have read a lot of other question and answers blog on stackoverflow , and I tried to use observable as you can see in the code. But when I click on submit button , the line of code inside ngOnInit() ( this.loginService.getLogged().subscribe((logged) => { ) is not getting called in order to update the value of isUserLoggedIn .
How can I broadcast or trigger some mechanism and what are the ways and the best way of doing it.
I don't know what mistake I am doing.
My other question is how can the methods in header-content can communicate with its siblings main-content or footer-content and also with the parent my-app component section.As in many questions answer is there for parent child components but not for the siblings.
Any help is appreciated !!!
Thanks
Upvotes: 0
Views: 477
Reputation: 1687
After doing too much of experiment I found the mistake which I was doing, instead of creating a separate Login service, I made it as shared service and I removed the statement providers:[LoginService]
from every component and placed this line of code inside app.module.ts file .
HeaderComponent.ts
ngOnInit(): void {
this.getUserName();
// Will fire everytime other component use the setter this.sharedService.setLogged()
this.sharedService.getLogged().subscribe((logged) => {
console.log("logged==", logged);
this.isUserLoggedIn = logged;
this.user = this.sharedService.getUserName();
});
}
Upvotes: 0
Reputation: 3848
In your login-service
you call the method that returns the username
.
That means that there you have a promise.
So back in your headerComponent change the get function to this:
getUserName() :void {
this.user = this.loginService
.getUserName()
.success(data => {
this.isUserLoggedIn = true;
}
}
I believe this will fix your problem based on what I see here. I would suggest to create a working snippet though ;)
UPDATE
Based on your comments I suggest you to use BehaviorSubject
which makes life easy to broadcast from service to component anything you want (from booleans to objects etc).
Here's an example based in your case:
In your login service (I'm attaching only the code that will make this happen):
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Injectable } from '@angular/core';
@Injectable()
export class LoginService {
userUpdated: any;
constructor() {
this.userUpdated = new BehaviorSubject<any>(false);
}
getUserName() :void {
this.user = this.loginService
.getUserName()
.success(data => {
this.userUpdated.next(true);
return data;
}
}
}
Next you go to you headerComponent code and edit it like this to subscribe to this:
@Component({
moduleId : module.id,
selector : 'header-content',
templateUrl: 'Header.html',
providers: [LoginService]
})
export class HeaderComponent implements OnInit, OnDestroy {
isUserLoggedIn = false;
user : string;
sub: any;
constructor(private loginService: LoginService) { }
ngOnInit(): void {
this.sub = this.loginService.userUpdated.subscribe(
data => {
if(data.username) {
this.isUserLoggedIn = true;
}
);
}
ngOnDestroy() {
this.sub.unsubscribe();
}
}
Upvotes: 1