Reputation: 1138
I'm currently building an Angular application, where I was trying to make the code highly reusable with the help of directives(as components).
<div class="container container-fluid" >
<div class="row">
<table class="table table-responsive table-hover">
<thead class="thead-inverse">
<tr>
<th *ngFor="let column of columns">{{column.header}}</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let row of rows;trackBy: trackByID;">
<td *ngFor="let column of columns">{{row[column.field]}}
</td>
</tr>
</tbody>
</table>
</div>
<xfd-progressbar></xfd-progressbar>
<div class="row col-lg-offset-5">
<ngbd-pagination-basic></ngbd-pagination-basic>
</div>
</div>
The above is a directive I created to have a reusable table. My general requirement was that I'll have one table per page.
Here's the corresponding component for the same -
import {Column} from "../models/Column";
import {Component, OnInit} from "@angular/core";
import {PaginationService} from "../services/PaginationService";
import {GridLoadUtil} from "../util/GridLoadUtil";
import {ProgressBarService} from "../services/ProgressBarService";
/**
* Created by ppandey on 6/12/2017.
*/
@Component({
selector: 'xfd-table',
templateUrl: './table.component.html',
styleUrls: ['./table.component.css']
})
export class TableComponent implements OnInit{
columns: Column[]= [];
rows: any[] = [];
constructor(private paginService: PaginationService,
private tableLoader: GridLoadUtil,
private progressBarService: ProgressBarService) {
this.paginService.itemsToDisplayChange.subscribe((value) => {
this.rows = value
});
this.tableLoader.columnsChange.subscribe((values) => {
this.columns = values;
});
}
ngOnInit() {
this.tableLoader.beforeDataLoaded();
this.progressBarService.startProgress();
}
}
As you can see, my component uses Services(GridLoadUtil), to provide it with the data, which makes the code highly decoupled.
Here's where I got into a pickle. If I want to have multiple tables on a single page, with different data and structure, it can't as the service to which each component is tied to is Singleton.
I can choose not to inject the service, and provide each service as a setter, but in that case, I will need to create subclasses for each service, which currently I didn't need to. Also, my code will become coupled.
Is there any direction that you guys think I can take to solve this problem?
Thanks, Pratik
Upvotes: 1
Views: 236
Reputation: 657338
You can create a directive to provide the service there.
Angulars DI will find that provider when it looks for the TableLoader
service, because it's the closest to the component (if the component doesn't provide one itself):
@Directive({
selector: [tableLoader1],
providers: [{provide: GridLoadUtil, useClass: GridLoadUtil1}],
})
class TableLoader1Directive {}
@Directive({
selector: [tableLoader2],
providers: [{provide: GridLoadUtil, useClass: GridLoadUtil2}],
})
class TableLoader2Directive {}
Then you can use it like
<xfg-table tableLoader1></xfg-table>
<xfg-table tableLoader2></xfg-table>
Upvotes: 1