每个(一组)组件的 angular 服务的单独实例
Seperate instances of an angular service per (set of) component(s)
TLDR:
如何将 Angular (6) 服务的一个实例用于一组(的实例)组件(和指令),并将另一个实例用于另一组相同的组件。
或提供更多信息:
我目前正致力于在基于 Angular 6 的应用程序中向 tables 添加排序功能。因为我使用的是自定义样式(基于具体化),所以大多数库都不适合我。我发现 this 很好的例子,尽管它完全独立于所使用的样式。
它创建一个 SortableColumnComponent
添加到每个 <th>
header 和一个 SortableTableDirective
添加到 <table>
元素。他们通过 SortService
进行通信,该 SortService
基本上只提供一个 RxJS 主题,以便在排序 direction/attribute 更改时通知其他列。
这里的问题是,只要一次只显示一个 sortable table,这个方法就很好用。但是,一旦添加更多,排序一次只能应用于一个(因为它们都共享相同的服务)。
根据 angular docs ,当您仅将服务注入应用程序根目录时(我这样做了),服务会自动变成单例。所以我试着只将它注入 sortableColumn:
@Component ({
selector: '[sortable-column]',
templateUrl: './sortable-column.component.html'
providers: [SortService]
})
但是每一列似乎都有自己的服务版本并且可以同时排序(这显然不能按预期工作)。
所以总的问题是:如何将 angular 服务的一个实例分配给一个(一个)组件(SortableTableDirective
)和匹配的 SortableColumnComponent
组件和其他 tables.
的同一服务的另一个实例
为了让这个更清楚,这就是我想要实现的目标:
-------------------------------------------------------------------------
| 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 |
-------------------------------------------------------------------------
或者有没有办法直接将某些列组件绑定到 table 指令并删除该服务?我在这里似乎缺少 "linking" 这个概念。
您不应在组件中提供服务,而应在 AppModule 中提供服务,并且 'inject' 通过在构造函数中创建属性来提供您的服务。
service.ts
@Injectable({
providedIn: 'root'
})
export class MyService {
}
编辑:
component.ts
@Component ({
selector: '[sortable-column]',
templateUrl: './sortable-column.component.html'
})
constructor(private myService: MyService) {}
appModule.ts
@NgModule({
declarations:[component],
imports: [YourModules],
providers: [MyService],
bootstrap: [component]
})
export class AppModule {}
阅读更多内容后,我发现另一个 part of the angular docs(最后一段)终于让我走上了正确的轨道:您可以通过将提供程序加载到组件中来限制它的范围。然后它仅对组件及其子组件可用(!)。在这种情况下正是我需要的。
当我第一次尝试时,我犯了一个错误,即在列中加载服务,从而为每个服务提供不同的实例。在 table 指令中加载它效果很好,因为这为 table 和所有子元素(例如列)提供了一个实例。 table 指令的另一个实例然后加载该服务的另一个实例,它允许我对所有 table 进行独立排序。
代码:
@Directive({
selector: '[sortable-table]',
providers: [SortService]
})
为了将来救人,现在我们可以使用Hierarchical Dependency Injection
在 Table 组件中,将您的服务放在 [providers] 中,并使用 @Host 装饰器标记依赖注入。在children中,标记为@SkipSelf.
现在,children 将忽略它们的“自身”实例并开始在标有@Host 的parent 中搜索服务。
查看示例:
Parent
@Component({
selector: 'table-component',
providers: [TableService],
templateUrl: './table.component.html',
styleUrls: ['./table.component.scss'],
})
export class TableComponent {
constructor(@Host() private tableService: TableService)
}
Child
@Component({
selector: 'child-component',
templateUrl: './child.component.html',
styleUrls: ['./child.component.scss'],
})
export class ChildComponent{
constructor(@SkipSelf() private tableService: TableService)
}
TLDR:
如何将 Angular (6) 服务的一个实例用于一组(的实例)组件(和指令),并将另一个实例用于另一组相同的组件。
或提供更多信息:
我目前正致力于在基于 Angular 6 的应用程序中向 tables 添加排序功能。因为我使用的是自定义样式(基于具体化),所以大多数库都不适合我。我发现 this 很好的例子,尽管它完全独立于所使用的样式。
它创建一个 SortableColumnComponent
添加到每个 <th>
header 和一个 SortableTableDirective
添加到 <table>
元素。他们通过 SortService
进行通信,该 SortService
基本上只提供一个 RxJS 主题,以便在排序 direction/attribute 更改时通知其他列。
这里的问题是,只要一次只显示一个 sortable table,这个方法就很好用。但是,一旦添加更多,排序一次只能应用于一个(因为它们都共享相同的服务)。
根据 angular docs ,当您仅将服务注入应用程序根目录时(我这样做了),服务会自动变成单例。所以我试着只将它注入 sortableColumn:
@Component ({
selector: '[sortable-column]',
templateUrl: './sortable-column.component.html'
providers: [SortService]
})
但是每一列似乎都有自己的服务版本并且可以同时排序(这显然不能按预期工作)。
所以总的问题是:如何将 angular 服务的一个实例分配给一个(一个)组件(SortableTableDirective
)和匹配的 SortableColumnComponent
组件和其他 tables.
为了让这个更清楚,这就是我想要实现的目标:
-------------------------------------------------------------------------
| 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 |
-------------------------------------------------------------------------
或者有没有办法直接将某些列组件绑定到 table 指令并删除该服务?我在这里似乎缺少 "linking" 这个概念。
您不应在组件中提供服务,而应在 AppModule 中提供服务,并且 'inject' 通过在构造函数中创建属性来提供您的服务。
service.ts
@Injectable({
providedIn: 'root'
})
export class MyService {
}
编辑:
component.ts
@Component ({
selector: '[sortable-column]',
templateUrl: './sortable-column.component.html'
})
constructor(private myService: MyService) {}
appModule.ts
@NgModule({
declarations:[component],
imports: [YourModules],
providers: [MyService],
bootstrap: [component]
})
export class AppModule {}
阅读更多内容后,我发现另一个 part of the angular docs(最后一段)终于让我走上了正确的轨道:您可以通过将提供程序加载到组件中来限制它的范围。然后它仅对组件及其子组件可用(!)。在这种情况下正是我需要的。
当我第一次尝试时,我犯了一个错误,即在列中加载服务,从而为每个服务提供不同的实例。在 table 指令中加载它效果很好,因为这为 table 和所有子元素(例如列)提供了一个实例。 table 指令的另一个实例然后加载该服务的另一个实例,它允许我对所有 table 进行独立排序。
代码:
@Directive({
selector: '[sortable-table]',
providers: [SortService]
})
为了将来救人,现在我们可以使用Hierarchical Dependency Injection
在 Table 组件中,将您的服务放在 [providers] 中,并使用 @Host 装饰器标记依赖注入。在children中,标记为@SkipSelf.
现在,children 将忽略它们的“自身”实例并开始在标有@Host 的parent 中搜索服务。
查看示例:
Parent
@Component({
selector: 'table-component',
providers: [TableService],
templateUrl: './table.component.html',
styleUrls: ['./table.component.scss'],
})
export class TableComponent {
constructor(@Host() private tableService: TableService)
}
Child
@Component({
selector: 'child-component',
templateUrl: './child.component.html',
styleUrls: ['./child.component.scss'],
})
export class ChildComponent{
constructor(@SkipSelf() private tableService: TableService)
}