The Class Set encounters an issue when trying to invoke an expression without a call signature, specifically when utilizing the BehaviorSubject and Observable

When I attempt to set a new Item, I am encountering the following error as per the title:

Cannot invoke an expression whose type lacks a call signature. Type 'ItemModel' has no compatible call signatures.

To share a selected Item between different states, I am utilizing BehaviorSubject and Subject. Essentially, my goal is to set a chosen Item and then retrieve it when navigating to its details page.

In my item.model.ts, let's assume it only contains an id property:

export class ItemModel {
    public id: string;
    constructor( id: string ) {
        this.id = id;
    }
}

Here's how my item.service.ts is used 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 sets a specific 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]);
    }

}

In the details.page.ts, I aim to retrieve 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));

     }

 }

Various attempts have been made to resolve the issue with invoking the setter method, including casting types and exploring different solutions mentioned in Stack Overflow threads and TypeScript GitHub issues.

If you can help identify what I'm doing wrong and suggest how to ensure ItemModel has a compatible signature, it would be greatly appreciated!

UPDATE

Thanks to assistance received, the initial error has been addressed. However, there persists an issue where the logged output inside ngOnInit of details.page.ts shows null, despite the correct output being displayed inside the setter.

Answer №1

itemService.item is a setter and should be accessed like a property rather than called as a function:

this._itemService.item = item;

According to 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']

If you are facing a null vs item problem :

The issue may arise because the service should be declared inside an NgModule instead of within a component (therefore, removing it from the components providers):

@NgModule({
  imports:[CommonModule],
  declarations:[SomeComponent],
  providers:[ItemService]
})
export class myModule{}

When a service is declared within a component's providers, it is only accessible to that specific component, its directives, and children. (Further explanation can be found in this thread.) This means there may be different instances of the service being utilized in DetailsPage and ItemComponent.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Angular5: The property 'showNavigationArrows' cannot be bound to 'ngb-carousel' because it is not recognized as a valid property

Currently, I am utilizing ng-bootstrap 1.x.x alongside Angular5 and bootstrap4. My goal is to customize the NavigationArrows based on dynamic data, however, I am encountering an issue while trying to access it from HTML. Here is a snippet of my code: imp ...

Changing the Id in Angular 2 Routing: A Step-by-Step Guide

Currently, I am working on an Angular 2 project with routing implementation. In the app.routing.module.ts file: { path: '', component: CComponent }, { path: 'Ddata:id', component: DComponent, children: [ { path: &apo ...

Using the scrollIntoView method on an element with a height of 0 within an Angular 2+ application

I am currently working with the following HTML code snippet: <div class="row-20 st-margin" *ngIf="role == 'Administrator'" id="hr-data"> <div class="col-md-12"></div> </div> After ...

"Adjusting the position of an Ionic Menu on-the-fly

As I strive to update the Ionic 3 Menu side dynamically when the user changes the language, a challenge arises for RTL languages where the menu needs to be on the right instead of the default left. To tackle this issue, I have subscribed to the TranslateS ...

Incorporating the Angular "dist" build file into the Node.js server.js script

Having some trouble deploying my MEAN stack app on Heroku. Managed to commit the app, but struggling to connect the ng build "dist" file to my server.js file. This is the snippet from my server.js file where I'm attempting to link the file: var dist ...

Angular directive for converting fields to title case

I have created a custom directive to transform all table column data into titlecase. The directive I implemented is designed to achieve this transformation, keeping in mind that pipes are not being counted: @Directive({ selector: '[appTitleCase]' ...

Using TypeScript to pass a callback function to labelFormatter in the legend of a Highcharts chart

I am currently experimenting with integrating HighCharts into an Angular2 project using TypeScript. My goal is to customize the appearance of the legend text, adding an image next to it. I've found that HighCharts provides a labelFormatter property w ...

What steps can I take to troubleshoot the issue with ionicons not functioning properly?

After starting to work on my app with Ionic 2, the ionicons were displaying properly. But now, for some reason, they are not showing up at all. Do you have any idea why this might be happening? Is it necessary to add a specific library or something similar ...

What is the solution for resolving the Angular error 'Cannot read property "_co.x" of undefined'?

Currently, I am facing an issue with nested JSON objects on a form that sends data to a database. Despite trying the *ngIf statement as recommended in Angular 5 - Stop errors from undefined object before loading data, the view does not update even after th ...

What is the best tool for setting up an ftp connection to a z/OS mainframe and downloading files to the local machine within an angular web application?

My goal is to allow the user of the webapp to enter a specific file located on the server via a text field, and then have that file downloaded to their local machine. There's also an optional feature where the user can input the login credentials for ...

Tally the number of sub-labels associated with each main label

In my Angular 9 application, I am looking to separate an array based on the lable field. Within each separated array, I would like to determine the count based on the subLable field. This is the array I am working with: [ {"id":1,"socia ...

The Axios function is unable to read the 'Ok' value because of undefined properties

I suspect there is something missing in my argument, but I am attempting to call HttpStatusCode.Ok from the Axios Enum. Here is how I have implemented it: import { HttpStatusCode } from 'axios' console.log(HttpStatusCode.Ok) However, I encounte ...

I am encountering an issue where my application is not recognizing the angular material/dialog module. What steps can I take to resolve this issue and ensure that it functions properly?

For my Angular application, I am trying to incorporate two Material UI components - MatDialog and MatDialogConfig. However, it seems like there might be an issue with the placement of these modules as all other modules are functioning correctly except fo ...

Embrace the power of npm package within the Nest Framework

Is there a way to integrate the celebrate NPM package with the Nest Framework? The documentation only mentions the use of the class-validator package, but I have experience using the celebrate middleware for request validation in Express and other framew ...

Challenges with the NestJS JWT Module

Encountering difficulties with the JWTModule in NestJS. I keep receiving this error message, even after passing the secret directly into the configuration instead of through my env file. I'm unsure of what the issue might be. Error: secretOrPrivateKey ...

How to choose cypress elements that are text-free using Cypress

Currently, I am troubleshooting an issue with a dropdown menu that allows for invalid selections. Despite being labeled as "unavailable," users are still able to click on these options for the product. <select readonly="" class="size-sele ...

What is the correct way to utilize Array.reduce with Typescript?

My current approach looks something like this: [].reduce<GenericType>( (acc, { value, status, time }) => { if (time) { return { ...acc, bestValue: valu ...

Angular 2 - Changes in component properties not reflected in view

I'm currently delving into Angular 2 and as far as I know, interpolated items in the view are supposed to automatically update when their corresponding variable changes in the model. However, in the following code snippet, I'm not observing this ...

"Typescript React encounters issues with recognizing props handed over to a functional component, resulting in error code ts 274

Currently, I am engaged in a react project that involves typescript. The goal is to exhibit movie character details obtained from an API through individual cards for each character. This should be achieved by utilizing react functional components along wi ...

Updates made in the browser are not being reflected in the Jhipster 4 generated app

I have attempted the following solutions: Modifying webpack.dev.js by setting reload : true new BrowserSyncPlugin({ host: 'localhost', port: 9000, proxy: { target: 'http://localhost:906 ...