Angular 7's innovative method for handling singleton instances: Dynamic provider

In my Angular application, I have the ability to display lists of videos or articles along with their details.

There are two main components: ContentListPage and ContentDetailsPage, which serve the same purpose for both videos and articles.

The only difference lies in the services layer, where data is fetched either from YouTube or WordPress.

My goal is to have a single generic service that can be dynamically provided based on the current content type. However, using a factory provider results in a new service instance being created every time a component is initialized.

I initially followed the guidance on factory providers from the official documentation

While this approach works, it leads to a new service instance being created when navigating from ContentListPage to ContentDetailsPage.

I understand that this issue stems from how I am providing the service:

@Component({
  . . .
  providers: [contentServiceProvider]
})

However, I'm struggling to find a way to provide the service at a different level without encountering this side effect.

content.service.provider.ts

const contentServiceFactory = (http: HttpService, metaMediaService: MetaMediaService) => {

  let contentService;
  if (metaMediaService.currentMetaMedia.type === MetaMediaType.WORDPRESS) {
    contentService = new MediasService(http, metaMediaService);
  } else {
    contentService = new YoutubeService(http, metaMediaService);
  }
  return contentService;
};

export let contentServiceProvider = {
  provide: ContentService,
  useFactory: contentServiceFactory,
  deps: [HttpService, MetaMediaService]
};

@Component({
  . . .
  providers: [contentServiceProvider]
})
export class ContentListPage implements OnInit {

  constructor(public mediasService: ContentService<IContent>) {

content-details.page.ts

@Component({
  . . .
  providers: [contentServiceProvider]
})
export class ContentDetailsPage implements OnInit {

  constructor(public contentService: ContentService<IContent>) { }

content.service.ts

@Injectable({
  providedIn: 'root'
})
export abstract class ContentService<T extends IContent> {
  abstract getContentById(id: number): Observable<T>;
  abstract  getContents(): Observable<T[]>;
  abstract loadMore(): Observable<T[]>;
}

Answer №1

After consulting with a friend for advice, we decided to utilize an injector:

const mediaServiceProvider = (mediaService: MediaService, injector: Injector) => {
  if (mediaService.currentMedia.type === MediaType.WORDPRESS) {
    return injector.get(MediaContentService);
  } else {
    return injector.get(YouTubeContentService);
  }
};

export let contentProvider = {
  provide: MediaService,
  useFactory: mediaServiceProvider,
  deps: [MediaService, Injector]
};

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

Updating an object property within an array in Angular Typescript does not reflect changes in the view

I am currently delving into Typescript and Angular, and I have encountered an issue where my view does not update when I try to modify a value in an array that is assigned to an object I defined. I have a feeling that it might be related to the context b ...

Stop any modifications to the input data

We are currently in the process of building an angular application with Angular 5. Typically, our components have input and output parameters defined as shown below: export class MultipleItemPickerComponent implements OnInit { @Input() itemPickerHeader ...

Updating DynamoDB objects seamlessly in Lambda functions without any conflicts

I am currently working with example Objects that follow this interface structure: interface Car{ id: Number; name: String; tires: Wheel[] } interface Wheel{ id: Number; name: String; radius: Number; } My goal is to store these Car Objects in DynamoDB and ...

Issue encountered when utilizing TypeORM within NestJS: Unable to import Entity Repository

Issue with EntityRepository Import Despite having @nestjs/typeorm installed, VS Code is not recognizing the decorator I need to use. Any suggestions on how to resolve this? ...

Is there a way to use router.navigate conditionally when navigating?

I am currently dealing with a scenario where I have a table of entities. Upon clicking a row, the user is directed to another page which represents the entity (view page). The implementation utilizes router.navigate. The issue arises when an entity is del ...

Tips for effectively highlighting search text within HTML content without causing any issues

I am in search of a solution that can assist me in searching for specific terms within an HTML string while also highlighting them. I have the ability to remove the HTML content from the string, but this poses the problem of losing the context of the origi ...

Encountered an issue while trying to open the appointment editor in Angular Syncfusion Schedule - Getting an error message saying "Cannot read property '0

Utilizing the Syncfusion Angular schedule and looking to add a template for header quick information. https://i.stack.imgur.com/KI1Ie.png <ng-template #quickInfoTemplatesHeader let-data> <div *ngIf="data.elementTy ...

Understanding the integration of jQuery html attributes with Angular2

I am encountering an issue with a library that requires me to include the tag below in my image: data-zoom-image When I add this tag to my image: <img class="larger-picture" [src]="'images/'+item.picture" align="middle" data-zoom-image="&ap ...

What is the best way to establish a model using a date index?

I'm trying to access an API using Angular that returns an array with dates as indexes. After attempting to create a model, I encountered some issues. How should I modify it? This is what the API response looks like: { "Information": { " ...

utilize Java version specifically designed for integrating with Angular framework and SOAP web services

One question I've been pondering: we currently have a project built on Java 6 and GWT, but we're considering migrating to Angular (using SOAP web services). Will Java 6 be compatible with Angular for the backend, or will we need to upgrade to Jav ...

Issue: Error message - Unhandled promise rejection: NodeInjector error - ControlContainer not found

I'm having trouble validating a form and encountering an error. I tried implementing the suggestions provided in the following threads without success: Getting error suddenly in Angular Error: NodeInjector: NOT_FOUND [ControlContainer] Using forms i ...

Steps to retrieve the HTTP response from an ngxs action

Is it possible to receive an HTTP response in a component without storing the result? I want to use the response directly in the component without saving it. How can I achieve this? @Action(GetNovels, { cancelUncompleted: true }) getNovels(ctx: StateCont ...

What could be causing my TypeScript object to appear as "undefined" when I try to log it?

I created a StackBlitz demo featuring a button that, when clicked, should pass a value to the controller. In the controller, there is a function designed to assign this value to an object. However, TypeScript seems to be indicating that the object is undef ...

ngFor loop is not displaying the correct values from the JSON object

Having some trouble making a REST call and displaying the results obtained. I've managed to successfully work with a simpler JSON data structure, but I'm struggling to get ngFor to properly process this particular data structure. I've tried ...

Removing a Request with specified parameters in MongoDB using NodeJS

Working with Angular 4 and MongoDB, I encountered an issue while attempting to send a delete request. My goal was to delete multiple items based on their IDs using the following setup: deleteData(id) { return this.http.delete(this.api, id) } In order ...

Establish a comprehensive background for your Angular project

I've been struggling to figure out how to set a background image for my entire angular project. I've tried using global css and the app.component.css file, but it only sets the background for the component area. Here is a snippet from my global ...

Issue with assigning Type (Date|number)[][] to Array<,Array<,string|number>> in Angular with typescript and google charts

Currently, I am utilizing Angular 8 along with the Google Charts module. My latest endeavor involved creating a Google Calendar Chart to complement some existing Google charts within my project. However, upon passing the data in my component.html file, I ...

Recovering the .angular/cache folder - a step-by-step guide

Recently, I went through the process of upgrading my Angular project from version 8 to version 17. While cleaning up, I ended up deleting the '.angular' folder as I noticed that my project's compilation time had increased after the upgrade. ...

When I bring in a component from my personal library, it will assign the type "any" to it

I'm facing an issue when trying to import a component from my own library. The component within the library is actually sourced from another one (so I import the component, customize it, and then export the customized version). However, upon importi ...

Optimal strategies for managing server-side validation/errors in Angular applications

Back in the day, I used to retrieve HTTP responses with a TypeScript object. validateTokenHttp(token: string): Observable<User> { return this.http.get<User>(`${environment.api}/auth/verifyToken/${token}`); } Sometimes it would return a Us ...