Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Seperate instances of an angular service per (set of) component(s)

TLDR:

How do I use one instance of an Angular (6) service for one set of (instances of) components (and directives) and another one for another set of the same components.

Or with more information:

I am currently working on adding a sorting feature to tables in my Angular 6 based application. Because I am using custom styles (materialize based) most libraries aren't working for me. I found this great example though which is totally independent of the styles used.

It creates a SortableColumnComponent that gets added to each <th> header and a SortableTableDirective that gets added to the <table> element. They communicate via a SortService that basically just provides a RxJS subject to notify other columns when the sorting direction/attribute changes.

The problem here is that this works great as long as only one sortable table is shown at a time. Once you add more though, sorting can only be applied to one at a time (as they all share the same service).

According to the angular docs a service becomes a singleton automatically when you inject it only into the application root (which I did). So instead I tried to inject it only into the sortableColumn:

@Component ({
    selector: '[sortable-column]',
    templateUrl: './sortable-column.component.html'
    providers: [SortService]
})

but then each column seems to get its own version of the service and can be sorted at the same time (which obviously does not work as intended).

So the overall question is: how can I assign one instance of an angular service to one (instance of a) component (the SortableTableDirective) and the matching SortableColumnComponent components and another instance of that same service to other tables.

To maybe make this clearer, this is what I am trying to achieve:

-------------------------------------------------------------------------
| page                                                                  |
|                                                                       |
| table 1 - SortableTableDirective - using instance 1 of sortingservice |
|   th 1 - sortablecolumncomponent - using instance 1 of sortingservice |
|   th 2 - sortablecolumncomponent - using instance 1 of sortingservice |
| ....                                                                  |
| table 2 - SortableTableDirective - using instance 2 of sortingservice |
|   th 1 - sortablecolumncomponent - using instance 2 of sortingservice |
|   th 2 - sortablecolumncomponent - using instance 2 of sortingservice |
-------------------------------------------------------------------------

Or is there a way to bind certain column components to the table directive directly and just remove the service? There seems to be this one concept of "linking" that I am missing here.

like image 469
CodeO Avatar asked Aug 09 '18 20:08

CodeO


People also ask

Can we create multiple instances of service in Angular?

It will create multiple instances of a service. Every time a new instance of provided service will be created when a component is used inside another component.

How many instances of service is created in Angular?

In this article we'll explore when and why Angular creates two instances of the same service and what solutions exist to ensure a service remains a singleton in the entire application.

Are services singleton in Angular?

Providing a singleton servicelink There are two ways to make a service a singleton in Angular: Set the providedIn property of the @Injectable() to "root" Include the service in the AppModule or in a module that is only imported by the AppModule.

What are different services in Angular?

There are two types of services in angular: Built-in services – There are approximately 30 built-in services in angular. Custom services – In angular if the user wants to create its own service he/she can do so.


1 Answers

After reading some more I found another part of the angular docs (last paragraph) that finally got me on the right track: you can limit the provider scope by loading it in a component. Then its available only to the component and its children (!). Exactly what I need in this case.

When I first tried it I made the mistake of loading the service in the column and thereby providing a different instance to each one. Loading it in the table directive works great as this provides one instance to the table and all child elements (e.g. the columns). Another instance of the table directive then loads another instance of the service which allows me to sort all tables independently from each other.

Code:

@Directive({
  selector: '[sortable-table]',
  providers: [SortService]
})
like image 115
CodeO Avatar answered Oct 22 '22 19:10

CodeO