使用服务/广播的组件通信:Angular2

时间:2016-11-18 14:56:16

标签: angular angular2-components

大家好我是angular2的初学者。我正在创建一个用于学习目的的小型演示应用程序。

app.component.ts

template: `
    <header-content></header-content>
    <main-content></main-content>
    <footer-content></footer-content>
  `

在我的标题中,我有一个导航部分,如主页,登录等。

主要内容模板结构

<div class="container main">
        <div class="row">
          <router-outlet></router-outlet>
        </div>
 </div> 

正如您所看到的,我已将主页内容中的页眉和页脚部分链接的路由器插座放置。

enter image description here

通过defalut我在登录页面/登录。

我为每个链接都有一个单独的组件。

我想要的是当用户点击登录页面上的提交按钮时,我将他重定向到其他一些xyz页面。但是我希望我的登录链接从标题导航中隐藏并显示用户名。

   <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);
     });
  }
}

登录-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;
    }
}

我已经在stackoverflow上阅读了很多其他问题和答案的博客,我尝试使用observable,你可以在代码中看到。但是当我点击提交按钮时,为了更新isUserLoggedIn的值,没有调用ngOnInit()(this.loginService.getLogged()。subscribe((logged)=&gt; {)中的代码行。

我如何广播或触发某种机制,以及采用哪种方式和最佳方式。

我不知道我在做什么错误。

我的另一个问题是 header-content 中的方法如何与其兄弟主要内容页脚内容进行通信,以及与父我的应用程序组件部分。在许多问题中,答案是父子组件,而不是兄弟姐妹。

任何帮助表示赞赏!!!

谢谢

2 个答案:

答案 0 :(得分:1)

login-service中,您调用返回username的方法。 这意味着你有一个承诺。

回到headerComponent,将get函数更改为:

getUserName() :void {
      this.user = this.loginService
                      .getUserName()
                      .success(data => {
                             this.isUserLoggedIn = true;
                      }
  }

我相信这会根据我在这里看到的问题解决您的问题。 我建议创建一个工作片段;)

<强>更新 根据您的评论,我建议您使用BehaviorSubject,这样可以轻松地从服务广播到您想要的任何组件(从布尔到对象等)。

以下是基于您案例的示例:

在您的登录服务中(我只附加将导致这种情况发生的代码):

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;
                        }
    }

}

接下来,您将转到headerComponent代码并对其进行编辑,以便订阅:

@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();
  }
}

答案 1 :(得分:0)

在做了太多实验之后,我发现了我正在做的错误,而不是创建一个单独的Login服务,我把它作为共享服务,我从每个组件中删除了语句providers:[LoginService]并放置了这一行app.module.ts文件中的代码。

<强> 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();
      });
  }