I've gone through several articles and official Angular guides briefly but it seems that they couldn't help me to solve my task. And here is what I wanted and did.
Let's say I have Angular application with product listing page. Moreover this app will have category listing page and some N listing pages in future. As you can see they're quite similar and will have one component in common - data table.
<app-data-table [type]="'product'"></app-data-table>
Which is implemented like:
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();
}
}
So as you might guess already I meant to make this component service type agnostic. That's why I've created and injected that 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];
}
}
And at the end we have two services for products and categories with some simple 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 [];
}
}
The funny part here is that this implementation works exactly as a expected. So I'm passing type of table as product for product related page, category type is for category etc.
Question is did I do something incorrect from perspective of Angular style (providers, DI etc.) and do we have any way to implement such a requirement to be more Angular-ish?