Ryan Mann Ryan Mann - 1 month ago 10
TypeScript Question

How to pass an Object from a service to a component

For my website I want to have a cart that you can fill with items. At this moment I am trying to handle this using a service that contains the cart in the form of an object,

cart
, with functions that can add Items to it and also return the entire cart as a Promise. At the moment I am only able to add items to the cart, but as soon as I try to call
getCart()
from
cart.component.ts
, it seems to return a completely empty array unlike the one I would think it was storing. Am I going about this the incorrect way?

cart.service.ts

import {Injectable, EventEmitter} from '@angular/core';
import {Item} from '../../models/item.model';


@Injectable()
export class CartService{
public cart:Item[] = [];

constructor(){
}

updateCart(){ //just prints the cart size
console.log('cart size: ' + this.cart.length);
}
addItem(item:Item){ //adds an item
this.cart.push(item);
this.updateCart();
}
checkout(){ //wipes cart
console.log('cart wiped');
this.cart = [];
this.updateCart();
}


getCart(): Promise<Item[]>{ //returns the cart
console.log('getting cart');
this.updateCart();
return Promise.resolve(this.cart);
}
}





cart.component.ts

import {Component, OnInit} from '@angular/core';
import { CartService } from './cart.service';
import {Item} from '../../models/item.model';


@Component({
moduleId: module.id,
selector: 'sd-cart',
templateUrl: 'cart.component.html',
styleUrls: ['cart.component.css'],
providers: [CartService]
})

export class CartComponent implements OnInit{
public cart: Item[];
constructor(private cartService:CartService){
this.cartService.getCart().then(cart => this.cart = cart);
if (!this.cart)
console.log('error getting cart');
else console.log(this.cart.length + ' got cart');
}
ngOnInit(){

}
}


The problem that I am having is whenever I add
Item
s to the cart from another component it will correctly show the length of the
cart
from the service (
console.log('cart size: ' + this.cart.length);
) But as soon as I load the component (triggering the constructor for the component) that same
console.log()
will print that the array is 0 regardless of how many items I have added to it. Inside of
cart.component.ts
, the
if (!this.cart) console.log('error getting cart');
also triggers from the call:
this.cartService.getCart().then(cart => this.cart = cart);
. I've looked at many tutorials and even tried somebody else's cart service and haven't had much luck with anything.

Answer

Don't provide CartService everywhere where you inject it. This leads to every component getting its own instance

@Component({
  moduleId: module.id,
  selector: 'sd-cart',
  templateUrl: 'cart.component.html',
  styleUrls: ['cart.component.css'],
  providers: [CartService] // <<<== remove here
})

Only add the service to providers of the @NgModule(). These providers are hoisted in the applications root scope and only one instance will exist and passed to every constructor that depends on it.

Note: Lazy loaded modules have their own root scope and providers are not hoisted to the application root scope.

Comments