我制作了一个通用材料自动完成功能,我想将其用于不同的 API 数据,例如国家、人物、职位等。这些数据中的每一个都具有共同的属性:id、name。因此,我定义了一个接口:
export interface AutocompleteValue {
id?: number,
name: string
}
我还使用服务来获取这些数据,每个服务都扩展相同的结构。总有一个
getAll()
方法来获取数据。为此,我使用了扩展的泛型类型。
export class APIService<GetType> {
getAll(): Observable<T[]> {...};
}
最后,我有一个通用的自动完成角度材质组件可用于每种类型。
@Component({...})
export class AutoCompleteInput<Type extends AutocompleteValue, ServiceType extends GetAllProvider<Type>> implements ControlValueAccessor, MatFormFieldControl<Type | undefined> {
...
constructor(protected service: ServiceType, ...) {}
...
}
如果我想在某个地方使用它:
export class PositionsAutoComplete extends AutoCompleteInput<GetDto, PositionService> {
constructor(
@Inject(POSITION_SERVICE_TOKEN) protected override service: PositionService, ...){}
}
原来我需要提供注入代币...
@Inject(POSITION_SERVICE_TOKEN)
和export const POSITION_SERVICE_TOKEN = new InjectionToken<PositionService>('');
.
在app.component.ts中:
providers: [{ provide: POSITION_SERVICE_TOKEN, useClass: PositionService }]
到目前为止效果很好。但是,AutocompleteInput 还需要注入令牌,我不知道为什么?我在
AutoCompleteInput
的构造函数中出现以下错误:
类的参数“service”没有合适的注入令牌 “自动完成输入”。考虑使用@Inject装饰器来指定 注入令牌。(-992003)
更新:我对通用服务也有类似的问题,我只需从通用类中删除
@Injectable
装饰器即可解决问题。我认为这很相似,@Component
实例化通用类,这需要一个InjectionToken
。如果删除 @Component
,我将无法在通用类 (autocomplete-input.component.html
) 中使用该模板。
您需要提供注入令牌,因为 Angular 不知道应该为 ServiceType 提供什么类。您是否有一项或多项扩展 getAllProvider 的服务?如果你有的话,直接提供即可。
如果你有很多,那么你就不能做你想做的事,至少不能以这种方式做。您必须在不同的组件中提供不同的服务,具体取决于某些组件需要什么服务