After going through various articles and official Angular guides, it appears that they were unable to assist me in solving my task. Here's what I wanted to achieve:
Imagine having an Angular application with a product listing page. Additionally, this app will include a category listing page and potentially more listing pages in the future. These pages are similar and share a common component - the data table.
<app-data-table [type]="'product'"></app-data-table>
This is how the implementation looks:
import {Component, Input, OnInit} from '@angular/core';
import {DataFactoryService} from "../data-factory.service";
@Component({
selector: 'app-data-table',
templateUrl: './data-table.component.html',
styleUrls: ['./data-table.component.css']
})
export class DataTableComponent implements OnInit {
@Input() type: string;
private data: any[];
constructor(private dataFactory: DataFactoryService) { }
ngOnInit(): void {
this.dataFactory.getServiceBy(this.type).selectAll();
}
}
To make this component service type agnostic, I created and injected the DataFactory
:
import { Injectable } from '@angular/core';
import {ProductService} from "./product.service";
import {CategoryService} from "./category.service";
import {DataService} from "./data.service";
@Injectable({
providedIn: 'root'
})
export class DataFactoryService {
private serviceTokenMapping = {
"product": ProductService,
"category": CategoryService
};
constructor() { }
public getServiceBy(token: string): DataService {
return new this.serviceTokenMapping[token];
}
}
For products and categories, we have two services with a basic abstract class:
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export abstract class DataService {
abstract selectAll(): any[];
}
import { Injectable } from '@angular/core';
import {DataService} from "./data.service";
import {Product} from "./product";
@Injectable({
providedIn: 'root'
})
export class ProductService implements DataService {
constructor() {}
public selectAll(): Product[] {
console.log(`ProductService...`);
return [];
}
}
import { Injectable } from '@angular/core';
import {DataService} from "./data.service";
import {Category} from "./category";
@Injectable({
providedIn: 'root'
})
export class CategoryService implements DataService {
constructor() {}
public selectAll(): Category[] {
console.log(`CategoryService...`);
return [];
}
}
This implementation works as expected, where the type of table (product or category) corresponds to the respective page. However, I'm curious if there are better Angular-style approaches for providers, DI, etc., to achieve such a requirement.