Issue with change detection in Angular 5 when providers are provided with useValue

Within my Angular 5 app, I have implemented a unique approach to connecting components and services. This is achieved through a 'broker' object which utilizes RXJS Subject fields to facilitate communication and command execution within the system. However, because there are no components directly injecting these services, they remain uncalled and undeclared.

To work around this issue, I have employed the use of the useValue field in the following manner:

import { NgModule } from '@angular/core';
import { DataBroker } from './brokers/data.broker';
import { SystemBroker } from './brokers/system.broker';
import { NotificationBroker } from './brokers/notification.broker';
import { LoggerService } from './services/logger.service';
import { SocketService } from './services/socket.service';
import { DataService } from './services/data.service';
import { SystemService } from './services/system.service';

// Instantiating necessary objects
const systemBroker: SystemBroker = new SystemBroker();
const dataBroker: DataBroker = new DataBroker();
const notificationBroker: NotificationBroker = new NotificationBroker();
const loggerService: LoggerService = new LoggerService(systemBroker);
const socketService: SocketService = new SocketService(loggerService, systemBroker, notificationBroker);
const dataService: DataService = new DataService(loggerService, socketService, dataBroker);
const systemService: SystemService = new SystemService(loggerService, socketService, systemBroker);

@NgModule({
  providers: [
    { provide: SystemBroker, useValue: systemBroker },
    { provide: DataBroker, useValue: dataBroker },
    { provide: NotificationBroker, useValue: notificationBroker },
    { provide: LoggerService, useValue: loggerService },
    { provide: SocketService, useValue: socketService },
    { provide: DataService, useValue: dataService },
    { provide: SystemService useValue: systemService },
  ]
})
export class AppServicesModule {
  constructor() { }
}

This method successfully creates instances; however, it presents another challenge where data passed through these services via the broker does not trigger change detection.

As an example, here is how data is transmitted through the broker using a snippet of code (this works correctly with the current workaround):

...
@Injectable()
export class DataService {
  constructor(dataBroker: DataBroker, socketService: SocketService) {
    socketService.on('NETWORK_CONFIG', (value: NetworkConfiguration) =>
      dataBroker.networkConfiguration.status.next(value));
  }
}

If I were to provide these objects in the typical way:

import { NgModule } from '@angular/core';
import { DataBroker } from './brokers/data.broker';
import { SystemBroker } from './brokers/system.broker';
import { NotificationBroker } from './brokers/notification.broker';
import { LoggerService } from './services/logger.service';
import { SocketService } from './services/socket.service';
import { DataService } from './services/data.service';
import { SystemService } from './services/system.service';

@NgModule({
  providers: [
    SystemBroker,
    DataBroker,
    NotificationBroker,
    LoggerService,
    SocketService,
    DataService,
    SystemService
  ]
})
export class AppServicesModule {
  constructor(systemBroker: SystemBroker
              dataBroker: DataBroker,
              notificationBroker: NotificationBroker,
              loggerService: LoggerService,
              socketService: SocketService,
              dataService: DataService,
              systemService: SystemService) { }
}

Everything functions as expected. While my current workaround suffices, I am interested in understanding the intended use case for the useValue if it behaves differently in this scenario. It may seem trivial, but finding the correct approach would be beneficial.

Anticipating the question, "why not simply use the services directly?" Our team frequently employs the broker pattern to seamlessly swap out service implementations without requiring modifications to our components.

Answer №1

Consider using a factory provider

let customDataServiceFactory = (customDataBroker: CustomDataBroker, customSocketService: CustomSocketService) => { return new CustomDataBroker(customDataBroker, customSocketService); };

export let  customDataServiceProvider= { provide: CustomDataService, useFactory: customDataServiceFactory, deps: [CustomDataBroker, CustomSocketService] };


@NdModule({
providers: [ customDataServiceProvider ]
})

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

Exploring the usage of asynchronous providers in NestJS

I am currently utilizing nestjs and I am interested in creating an async provider. Below is my folder structure: . ├── dist │ └── main.js ├── libs │ └── dma │ ├── src │ │ ├── client │ ...

How to retrieve a random element from an array within a for loop using Angular 2

I'm in the process of developing a soundboard that will play a random sound each time a button is clicked. To achieve this, I have created an array within a for loop to extract the links to mp3 files (filename), and when a user clicks the button, the ...

esBuild failing to generate typescript declaration files while running in watch mode

Recently dove into using edBuild and I have to say, it's been a breeze to get up and running - simple, fast, and easy. When I execute my esBuild build command WITHOUT WATCH, I can see that the type files (.d.ts) are successfully generated. However, ...

Difficulty with Bootstrap Carousel (image is displayed but fails to transition/change)

Although I don't have much experience in this, I've searched through various documentations and solutions that have helped others. Unfortunately, I haven't been able to fix my issue, so I decided to create my own post to seek assistance. &l ...

Discover the power of native script's two-way data binding in your classes

Is there a way to implement two-way binding in Nativescript? Here is my attempt: The variable CompModel is set to "FA I Test". I am looking for a solution where the data can be bound both ways - initially displaying the value "FA I Test" at the class lev ...

Can :[Interface] be considered a correct array declaration in Typescript?

My TypeScript codebase is filled with code snippets like the one below... export interface SomeType { name: string; } export interface SomeComposedType { things: [SomeType]; } Everything was working smoothly until I started experiencing issues su ...

Angular: Utilizing the new HttpClient to map HTTP responses

Within my application, I have a standard API service that communicates with the backend using requests structured like this: post<T>(url: string, jsonObject: object): Observable<T> { return this.http.post<T>(url, JSON.stringify(json ...

After using apt to install tsc, I find myself in a dilemma on how to either delete or upgrade it

After realizing I was missing Typescript on my server, I attempted to run the 'tsc' command. However, I received a message suggesting I use 'apt install tsc' instead. Without much thought, I executed the command. Normally, I would insta ...

Tips for embedding an object into an iframe source

I have successfully integrated a YouTube iframe into my HTML file. However, I would like the source URL to be dynamically generated based on data from the backend rather than manually inputting the URL as shown below. In the admin panel, there is an object ...

Angular 2.4.8's need for Node.js dependency

I recently started working with angular 2.4.8 and have been exploring tutorials on the angular website. However, I've noticed that all angular libraries are typically imported using node modules (via package.json for installing Node.js). Is it mandato ...

Issue with Angular App: Bootstrap navbar not displaying on smaller screens

I am working on an Angular app (using Angular 11.2.4 with Bootstrap 4.5.3) and facing an issue where the navbar is not rendering correctly on screens smaller than ~580 pixels wide. Even when I click the toggler to 'expand' the collapse region, n ...

Activate the Keypress event to update the input value in React upon pressing the Enter

I am facing an issue where I need to reset the value of an input using a method triggered by onPressEnter. Here is the input code: <Input type="text" placeholder="new account" onPressEnter={(event) => this.onCreateAccount(event)}> < ...

Monitor modifications to documents and their respective sub-collections in Firebase Cloud Functions

Is it possible to run a function when there is a change in either a document within the parent collection or a document within one of its subcollections? I have tried using the code provided in the Firebase documentation, but it only triggers when a docume ...

What exactly constitutes a project definition when it comes to Angular development?

After running my Angular project on Travis-CI, I encountered two exceptions: $ ng test The test command needs to be executed in an Angular project, but the project definition was not found. The command "ng test" exited with 1. $ ng e2e The e2e command re ...

Error in TypeScript: It is not possible to use a component with MUI styling as a JSX element

I can't figure out what's going wrong. I'm attempting to include a child component in the main page, and I have a feeling it has something to do with MUI styles being applied at the end. I removed all unnecessary code and still encounter thi ...

Utilizing the shared styling feature in a NativeScript app by incorporating it through the angular.json stylePre

Trying to implement Angular 6's stylePreprocessorOptions to easily import shared styling into a component using @import 'app'. My NativeScript project is part of a NxWorkspace setup, with its own angular.json file. Following the instructio ...

Communicating Data Between Controllers in Node.js

Within my PlantsController, I extract the Plants using the following method: function getAll() { const plants= HttpRequestPromise.get(config.ApiURL+'allPlants', config.head); return plants; } export class PlantsController { ... public ...

What is the best way to include a background image in an Angular selector?

I'm having trouble setting a background image for an Angular selector. Here's the code I'm using: <app-highway-card [ngStyle]="{'background-image':'url(https://cdn.pixabay.com/photo/2021/09/04/09/32/road-6597404__340.j ...

Changing the CSS properties of the Breadcrumb item using ngClass in Angular

I have been working on a Breadcrumb component in Angular that displays the full navigation path for routing purposes. This feature helps users navigate back to any previous step easily. I am using ActivatedRoute to get the current URL, which is functioning ...

Optimizing Angular: Configuring baseHref for assets during development with SSR

During production, we set the base href using the following command: ng build --base-href /app/ This configuration works smoothly as our assets are also accessible at /app/assets/, just as expected. However, I have been facing difficulties achieving the ...