How to share data between angular components?

2019-09-02 20:15发布

问题:

I am new to angular and trying to simulate a login.

I have a login component which is responsible for authenticating the user. In the response of the authenticate web service we are receiving an api key which should be sent in every subsequent request.

Once the user is logged in we change the path from /login to /dashboard.

Now in my dashboard component I am inject login component and calling getApiKey function which is returning undefined. Below is the code

import { Component, OnInit, Injectable } from '@angular/core';
import { User } from '../domain/User';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { LoginResponse } from '../domain/LoginResponse'

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.css']
})
@Injectable()
export class LoginComponent implements OnInit {

  private user:User = new User();

  private xSSOFamilyId:string = 'BOMO';

  private apiKey:string;

  constructor(private httpClient: HttpClient) { }

  ngOnInit() {
  }

  login(): void {

    var authorization:string = 'Basic ' + btoa(this.user.cwopa + ":" + this.user.password);
    var httpHeaders = new HttpHeaders({
      'Authorization': authorization,
      'userId': this.user.cwopa,
      'X-SSO-Family-Id': this.xSSOFamilyId
    });
    this.httpClient.post<LoginResponse>('http://localhost:8081/web-beginner/authenticate', undefined, {headers: httpHeaders}).subscribe(response => {
      this.apiKey = response.apiKey;
      console.log(this.apiKey)
      window.location.href = "dashboard";
    }, error => {
      console.log("error occured");
    });
  }

  public getApiKey(): string {
    return this.apiKey;
  }
}

dashboard.component.ts

import { Component, OnInit } from '@angular/core';

import {LoginComponent} from "../login/login.component"

@Component({
  selector: 'app-dashboard',
  templateUrl: './dashboard.component.html',
  styleUrls: ['./dashboard.component.css'],
  providers: [LoginComponent]
})
export class DashboardComponent implements OnInit {

  constructor(public loginComponent: LoginComponent) { }

  ngOnInit() {
  }

  authorize(appName:string): void {
    console.log(this.loginComponent.getApiKey())
  }
}

I am thinking of using session storage to set api key and then read the api key from the dashboard component. Is this fine or is there a better solution?

Can anyone please tell me how to share data between components?

回答1:

create Service

myservice.ts

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import 'rxjs/add/observable/of';
import 'rxjs/add/observable/from';

@Injectable()
export class MyService {

  thingTwoStream = new Subject();
  ApiKey = new BehaviorSubject<string>(null);

}

Then in your login component use next method to share value

import { Component, OnInit, Injectable } from '@angular/core';
import { User } from '../domain/User';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { LoginResponse } from '../domain/LoginResponse'
import { MyService} from './myservice';
@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.css']
})
@Injectable()
export class LoginComponent implements OnInit {

  private user:User = new User();

  private xSSOFamilyId:string = 'BOMO';

  private apiKey:string;

  constructor(private httpClient: HttpClient,private service:MyService) { }

  ngOnInit() {
  }

  login(): void {

    var authorization:string = 'Basic ' + btoa(this.user.cwopa + ":" + this.user.password);
    var httpHeaders = new HttpHeaders({
      'Authorization': authorization,
      'userId': this.user.cwopa,
      'X-SSO-Family-Id': this.xSSOFamilyId
    });
    this.httpClient.post<LoginResponse>('http://localhost:8081/web-beginner/authenticate', undefined, {headers: httpHeaders}).subscribe(response => {
      this.apiKey = response.apiKey;
      console.log(this.apiKey)
      window.location.href = "dashboard";
    }, error => {
      console.log("error occured");
    });
  }

  public getApiKey(): string {
    this.service.ApiKey.next(this.apiKey);
    return this.apiKey;
  }
}

Then subscribe inside your dashboard component

import { Component, OnInit } from '@angular/core';    
import {LoginComponent} from "../login/login.component"
import { MyService} from './myservice';

@Component({
  selector: 'app-dashboard',
  templateUrl: './dashboard.component.html',
  styleUrls: ['./dashboard.component.css'],
  providers: [LoginComponent]
})
export class DashboardComponent implements OnInit {

  constructor(public loginComponent: LoginComponent,private service:MyService) { }

  ngOnInit() {
     this.service.ApiKey.subscribe((data)=>console.log(data))
  }

  authorize(appName:string): void {
    console.log(this.loginComponent.getApiKey())
  }
}


回答2:

In my case, I created auth service which has login(), logout(), authenticated() functions. And There are 2 components and they use that auth service.

Furthermore, if you need to implement route path according to the login info. You can control them with auth guard (https://angular.io/guide/router)



标签: angular