简体   繁体   中英

Angular 2 - Using shared service pass data between components

My aim is to get the total quantity of my cart items and display it on my Cart link on navbar which is inside my main component.

Here is my cart service

import { Injectable } from '@angular/core';
import { Http, Response, Headers, RequestOptions } from '@angular/http';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import { Observable } from 'rxjs/Rx';

@Injectable()
export class CartService {
    totalQuantity: Number = 0;

    constructor(private _http: Http) { };

    getCartItems(userId) {
        let headers = new Headers({ 'Authorization': 'JWT ' + localStorage.getItem('currentUserToken') });
        let options = new RequestOptions({ headers: headers });
        return this._http.get('http://localhost:3000/cart/getitem/' + userId, options)
            .map((response: Response) => {
                this.totalQuantity = response.json().totalQuantity;
                return response.json();
            })
            .catch(this._handlerError)
    }

    updateCartItem(item){
        console.log(item);
        let headers = new Headers({ 'Authorization': 'JWT ' + localStorage.getItem('currentUserToken') });
        let options = new RequestOptions({ headers: headers });
        return this._http.post('http://localhost:3000/cart/updateitem/', item, options)
            .map((response: Response) => {
                this.totalQuantity = response.json().totalQuantity;
                return response.json();
            })
            .catch(this._handlerError)
    }

    removeCartItem(item){
        let headers = new Headers({ 'Authorization': 'JWT ' + localStorage.getItem('currentUserToken') });
        let options = new RequestOptions({ headers: headers });
        return this._http.post('http://localhost:3000/cart/deleteitem/', item, options)
            .map((response: Response) => {
                this.totalQuantity = response.json().totalQuantity;
                return response.json();
            })
            .catch(this._handlerError)
    }

    _handlerError(err: any) {
        console.log(err);
        // throw err;
        return Observable.throw(err);
    }
}

I made a public variable called totalQuantity and is filled with value after executing one of the cart services functions. This totalQuantity variable is accessed by app component.

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

import { loginStatusChanged } from './auth.guard';
import { CartService } from './cart';
import { UserService } from './user';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit{
  title = 'app works!';

  loginStatus: boolean;

  constructor(private _cartService: CartService, private _userService: UserService, private _router: Router){}

  totalQuantity = this._cartService.totalQuantity;

  onLogout(){
    this._userService.logout();
    loginStatusChanged.next(false);
    this._router.navigate(['/login']);
  }

  ngOnInit(){
    this.onLogout();
    loginStatusChanged.subscribe(status => this.loginStatus = status);
  }
}

I think the problem here is: 1. If the user doesn't execute a function from the cartService then the totalQuantity variable will never have a value. 2. How can I get the value of totalQuantity ONLY IF a user logged in.

Can anyone help me solve this problems please? I'm stuck.

I don't see your app.module.ts, but just to be sure, you need to add in your providers your CartService.

  1. If the user doesn't execute a function from the cartService then the totalQuantity variable will never have a value.

No, because you wrote that your totalQuantity is initialize at 0.

  1. How can I get the value of totalQuantity ONLY IF a user logged in.

In your sharedService, you can to a function that will get the totalQuantity by checkin if the user is logged in.

getTotalQuantity() {
   let isLoggedIn: boolean = methodThatCheckIfLoggedIn();
   if (isLoggedIn) 
      return this.totalQuantity;
   return null;
}

The title, 'using shared service pass data between components' suggests a design problem. If you wish to pass data between components you should probably do so by passing data between components ( @Input & @Output ).

Having a shared variable ( totalQuantity ) that is populated by some service methods introduces temporal coupling. The value is only correct if some other action has occurred before . I suggest that it may be better to make totalQuantity a method that fetches its own value. If you are worried about the performance cost and a willing to sacrifice consistency then you could cache the value within the method.

Finally, if you don't want to do any of that, then just call one of the methods that updates totalQuantity from within the AppComponent constructor and then update totalQuantity .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM