Reputation: 3985
as stated in the title, I'm getting the following error when trying to set a new Item
:
Cannot invoke an expression whose type lacks a call signature. Type 'ItemModel' has no compatible call signatures.
I'm using BehaviorSubject
and Subject
to share a set Item
between two different states. Essentially, I want to set a chosen Item
and then, when going to its details page, get it.
Here's my item.model.ts
, let's suppose it has only an id
property:
export class ItemModel {
public id: string;
constructor( id: string ) {
this.id = id;
}
}
Here's my item.service.ts
use to get
and set
an Item
:
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { ItemModel } from './item.model';
@Injectable()
export class ItemService {
public _item = new BehaviorSubject<ItemModel>(null);
item$ = this._item.asObservable();
public set item(item: ItemModel) {
this._item.next(item);
}
public get item() : ItemModel {
return this._item.getValue();
}
}
My item.component.ts
would set a given Item
:
import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { ItemService } from '../item.service';
@Component({
selector: 'app-item',
templateUrl: './item.html',
styleUrls: ['./item.scss'],
providers: [ItemService]
})
export class ItemComponent {
constructor(private _router: Router, private _itemService : ItemService) { }
goToDetails(item : ItemModel){
this._itemService.item(item); //Throws the error
this._router.navigate(['/details', item.id]);
}
}
And on details.page.ts
I want to get that Item
:
import { Component } from '@angular/core';
import { Subscription } from 'rxjs/Subscription';
import { ItemService } from './item.service';
import { ItemModel } from './item.model';
@Component({
selector: 'app-details-page',
templateUrl: './details.page.html',
styleUrls: ['./details.page.scss'],
providers: [ItemService]
})
export class DetailsPage {
private _item = ItemModel;
private subscription : Subscription;
constructor( private _itemService: ItemService ) { }
ngOnInit() {
this.subscription = this._itemService.item$
.subscribe(item => console.log(item));
}
}
What I tried so far on the invocation of the setter:
item as ItemModel
item as typeof ItemModel
What Am I doing wrong? How can I make sure that ItemModel has a compatible signature?
EDIT
With @n00dl3 's help I was able to get rid of this error. But, unluckily, when logging inside details.page.ts
's ngOnInit
I get null
. When I log inside the setter it shows the correct output.
Upvotes: 4
Views: 2238
Reputation: 21564
itemService.item
is a setter so you should not call it like a function, but like a property :
this._itemService.item = item;
from MDN :
Defining a setter on new objects in object initializers This will define a pseudo-property current of object language that, when assigned a value, will update log with that value:
var language = { set current(name) { this.log.push(name); }, log: [] } language.current = 'EN'; console.log(language.log); // ['EN'] language.current = 'FA'; console.log(language.log); // ['EN', 'FA']
For your null vs item problem :
It is because you should not declare your service inside component, but inside an NgModule
(so you should remove it from your components providers):
@NgModule({
imports:[CommonModule],
declarations:[SomeComponent],
providers:[ItemService]
})
export class myModule{}
when you declare a service inside component's providers, it is only available to that component, dirrectives applied to it and its children. (More details in this question.) So it means you are currently not talking to the same service instance in DetailsPage
and in ItemComponent
.
Upvotes: 5