0

I have app component(for nav header) and auth component(for login).

They need both "isLoggedIn" property which can be useful for app to change its "login" button to "logout" and for auth to block login attempt after login.

But I don't know whether I can export? a property from one component to another.

I know I can use service but app doesn't have proper method to subscribe user service's mapped data.

How can I make them share "isLoggedIn" property?

Here are my auth component and app component with user-authentication service.

export class AuthComponent {

  private username = '';

  private password = '';

  private remembered: boolean = false;

  isLoggedIn: boolean; 

  constructor(private userAuthenticationService: UserAuthenticationService) {}

  onsubmit() { 
    this.userAuthenticationService
    .logIn({ username: this.username, password: this.password })
    .subscribe(response => {
      this.isLoggedIn = response["success"];
    });
  }

}

//auth.component.html
<div class="loginbox">
  <header>MAILBOY</header>
  <form *ngIf="!isLoggedIn; else loggedInMessage">
    <input type="text" [(ngModel)]="username" name="username" id="email" placeholder="이메일 주소"/>
    <input type="password" [(ngModel)]="password" name="password" id="password" placeholder="비밀번호"/>
    <label for="remember"><input type="checkbox" id="remember" [checked]="remembered" (change)="remembered = !remembered" />이메일 저장</label>
    <button class="login" (click)="onsubmit()">로그인</button>
    <h3>처음이신가요?</h3><button class="register"><a href="/register">회원가입</a></button>
  </form>  
  <ng-template #loggedInMessage>
    <h1>환영합니다! 메일 수신 여부를 설정해주세요.</h1>
  </ng-template>
</div>





export class AppComponent {

  isLoggedIn = 'false';

  constructor(private userAuthenticationService: UserAuthenticationService) { }

}

//app.component.html
<div class="headerSpacing">
        <nav>
            <a routerLink="/home" routerLinkActive="active">홈</a>
            <a *ngIf="isLoggedIn; else loggedInMessage" routerLink="/auth" routerLinkActive="active">로그인</a>   
                    <ng-template #loggedInMessage>
                            <a (click)="logOut()">로그아웃</a>
                    </ng-template>
            <a routerLink="/mail-setting" routerLinkActive="active">메일 수신 설정</a>
        </nav>
    </div>
    <router-outlet></router-outlet>

finally my user-authentication service

@Injectable()
export class UserAuthenticationService {

  headers = new Headers({
    'Content-Type': 'application/json'
  });

  constructor(private http: Http) { }

  /*
    body: {
      username,
      password,
    }
  */
  logIn(user: Object) {
    return this.http
    .post('/auth/login', JSON.stringify(user),
    { headers: this.headers })
    .map(data => { console.log(data);
      return data.json() });
  }

  private handleError(error: any): Promise<any> {
    console.log('An error occurred ', error);
    return Promise.reject(error.message || error);
  }

}
Gompro
  • 2,247
  • 1
  • 16
  • 26

1 Answers1

2

You can use a BehaviorSubject here.

In UserAuthenticationService:

import { BehaviorSubject } from 'rxjs';

export class UserAuthenticationService {
   private loggedIn = new BehaviorSubject(false);

   // call this when you want to set loggedIn to true
   login() {
     this.loggedIn.next(true);
   }

   getIsLoggedIn() {
     return this.loggedIn;
   }
}

In app or auth component or any component that you need the value you can subscribe to it:

constructor(private userAuthenticationService: UserAuthenticationService) {
   userAuthenticationService.getIsLoggedIn().subscribe(bool => {
     // use bool value here, you can set local var
     // this.isLoggedIn = bool;
   });
}
Eeks33
  • 2,245
  • 1
  • 14
  • 17
  • All your components should get the loggedIn value from one place, this is the BehaviorSubject in your service as per my answer. They can all easily subscribe to it and then take action accordingly. If you combine my answer with your code you can easily achieve that. Your line
    will be fine because you can set this value in the subscribe block of the loggedIn value. Once you do all that you will need to look into implementing guards to block the route: https://blog.thoughtram.io/angular/2016/07/18/guards-in-angular-2.html
    – Eeks33 May 10 '17 at 03:53