Angular 2 — Использование общих данных передачи службы между компонентами

Моя цель - получить общее количество товаров в моей корзине и отобразить его по ссылке "Корзина" на панели навигации, которая находится внутри моего основного компонента.

Вот моя корзина

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

Я создал общедоступную переменную с именем totalQuantity и заполнил ее значением после выполнения одной из функций обслуживания корзины. К этой переменной totalQuantity обращается компонент приложения.

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

Я думаю, проблема здесь в следующем: 1. Если пользователь не выполняет функцию из cartService, тогда переменная totalQuantity никогда не будет иметь значения. 2. Как я могу получить значение totalQuantity ТОЛЬКО ЕСЛИ пользователь вошел в систему.

Может ли кто-нибудь помочь мне решить эту проблему, пожалуйста? Я застрял.


person Mix Austria    schedule 13.01.2017    source источник


Ответы (2)


Я не вижу вашего app.module.ts, но чтобы быть уверенным, вам нужно добавить в своих провайдеров свой CartService.

  1. Если пользователь не выполняет функцию из cartService, тогда переменная totalQuantity никогда не будет иметь значения.

Нет, потому что вы написали, что ваш totalQuantity инициализируется равным 0.

  1. Как я могу получить значение totalQuantity, ТОЛЬКО ЕСЛИ пользователь вошел в систему.

В вашем sharedService вы можете использовать функцию, которая получит totalQuantity путем регистрации, если пользователь вошел в систему.

getTotalQuantity() {
   let isLoggedIn: boolean = methodThatCheckIfLoggedIn();
   if (isLoggedIn) 
      return this.totalQuantity;
   return null;
}
person Gabriel Rousseau-Filion    schedule 13.01.2017

Название «использование общих данных передачи службы между компонентами» предполагает проблему проектирования. Если вы хотите передавать данные между компонентами, вы, вероятно, должны сделать это, передавая данные между компонентами (@Input и @Output).

Наличие общей переменной (totalQuantity), заполняемой некоторыми сервисными методами, приводит к временной связи. Значение верно только в том случае, если какое-то другое действие произошло до. Я полагаю, что лучше сделать totalQuantity методом, который извлекает собственное значение. Если вы беспокоитесь о стоимости производительности и готовы пожертвовать согласованностью, вы можете кэшировать значение в методе.

Наконец, если вы не хотите делать ничего из этого, просто вызовите один из методов, который обновляет totalQuantity из конструктора AppComponent, а затем обновите totalQuantity.

person liammclennan    schedule 13.01.2017
comment
можете ли вы предложить, где я должен поместить метод, который обновляет totalQuantity в AppComponent? потому что я почти уверен, что он не перейдет к onInit, потому что после инициализации AppComponent нет пользователя, вошедшего в систему. - person Mix Austria; 13.01.2017