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[]>;
}