TLDR:
如何将 Angular (6( 服务的一个实例用于一组组件(和指令(的(实例(,而将另一个实例用于另一组相同的组件。
或提供更多信息:
我目前正在为基于 Angular 6 的应用程序中的表添加排序功能。因为我使用的是自定义样式(基于物化(,所以大多数库都不适合我。我发现了这个很好的例子,它完全独立于使用的样式。
它创建一个添加到每个<th>
标头的SortableColumnComponent
和一个添加到<table>
元素的SortableTableDirective
。它们通过一个SortService
进行通信,该基本上只提供一个 RxJS 主题,以便在排序方向/属性更改时通知其他列。
这里的问题是,只要一次只显示一个可排序的表,这就可以很好地工作。但是,添加更多内容后,排序一次只能应用于一个(因为它们都共享相同的服务(。
根据角度文档,当您仅将服务注入应用程序根目录时,服务会自动成为单例(我做到了(。因此,我尝试仅将其注入可排序列:
@Component ({
selector: '[sortable-column]',
templateUrl: './sortable-column.component.html'
providers: [SortService]
})
但是,每列似乎都有自己的服务版本,并且可以同时进行排序(这显然不能按预期工作(。
所以总体问题是:如何将角度服务的一个实例分配给一个(一个(组件(SortableTableDirective
(以及匹配SortableColumnComponent
组件和同一服务的另一个实例到其他表。
也许更清楚地说明这一点,这就是我想要实现的目标:
-------------------------------------------------------------------------
| 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 指令并删除服务?我在这里似乎缺少一个"链接"的概念。
在阅读了更多内容后,我发现了角度文档的另一部分(最后一段(,最终让我走上了正确的轨道:您可以通过将其加载到组件中来限制提供程序范围。然后,它仅对组件及其子组件可用(!正是我在这种情况下所需要的。
当我第一次尝试它时,我犯了一个错误,即在列中加载服务,从而为每个服务提供不同的实例。在 table 指令中加载它效果很好,因为这为表和所有子元素(例如列(提供了一个实例。然后,table 指令的另一个实例加载服务的另一个实例,这允许我彼此独立地对所有表进行排序。
法典:
@Directive({
selector: '[sortable-table]',
providers: [SortService]
})
为了将来帮助某人,现在我们可以使用分层依赖注入
在表组件中,将服务放在 [提供程序] 中,并使用@Host装饰器标记依赖注入。在儿童中,用@SkipSelf标记。
现在,孩子们将忽略他们的"自我"实例,并开始在标有@Host的父项中搜索服务。
请参阅示例:
父母
@Component({
selector: 'table-component',
providers: [TableService],
templateUrl: './table.component.html',
styleUrls: ['./table.component.scss'],
})
export class TableComponent {
constructor(@Host() private tableService: TableService)
}
孩子
@Component({
selector: 'child-component',
templateUrl: './child.component.html',
styleUrls: ['./child.component.scss'],
})
export class ChildComponent{
constructor(@SkipSelf() private tableService: TableService)
}
您不应该在组件中提供服务,而是在 AppModule 中提供服务,并通过在构造函数中创建属性来"注入"您的服务。
服务.ts
@Injectable({
providedIn: 'root'
})
export class MyService {
}
编辑:
组件.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 {}