在组件树中获取对特定类型的所有指令的引用 [英] Obtaining references to all directives of a certain type up the component tree
问题描述
我有一个复杂的场景,需要帮助.
我有一个指令(称为TagDirective
),该指令放置在我的应用程序的多个元素上.我还有另一个指令(QueryDirective
),它需要引用其主机元素以及层次结构中位于其上方的所有元素上的所有TagDirective
实例.
示例:
<div appTag="a">
<div appTag="b">
<div appTag="c">
<div appTag="d">
<div appQuery>
<!-- In here I want to have a reference to TagDirectives instances
d,c,b,a -->
</div>
</div>
</div>
<div appTag="e">
<div appTag="f">
<div appTag="g">
<div appTag="h">
<div appQuery>
<!-- In here I want to have a reference to TagDirectives instances
h,g,f,e,b,a -->
</div>
</div>
</div>
<div appQuery>
<!-- In here I want to have a reference to TagDirectives instances
f,e,b,a -->
</div>
</div>
</div>
</div>
</div>
我知道我可以通过使注入器在QueryDirective
的构造函数中提供对单独在宿主元素上的TagDirective
的引用,我也知道我可以通过注入ViewContainerRef
获得下一个更高的实例,并且使用其parentInjector
成员请求类型为TagDirective
的实例.
但是,我还没有找到进一步深入树的方法,并一直收集所有实例直到根.
我将如何实现?谢谢!
由于每个元素都有其自己的注入器,因此我们不能仅使用multi: true
,只有在相同元素上提供相同标记的情况下,它才起作用./p>
可能的解决方法如下:
export const TAG_DIRECTIVES_TOKEN = new InjectionToken('tags directives');
export function tagDirectiveFactory(dir: TagDirective, token: TagDirective[]) {
return token ? [dir, ...token] : [dir];
}
@Directive({
selector: '[appTag]',
providers: [{
provide: TAG_DIRECTIVES_TOKEN,
useFactory: tagDirectiveFactory,
deps: [TagDirective, [ new SkipSelf(), new Optional(), TAG_DIRECTIVES_TOKEN ]]
}]
})
export class TagDirective {}
@Directive({
selector: '[appQuery]'
})
export class AppQueryDirective {
constructor(@Inject(TAG_DIRECTIVES_TOKEN) private directives: TagDirective[]){
console.log(directives);
}
}
在上面的代码中,我在每个div[appTag]
元素上提供TAG_DIRECTIVES_TOKEN
.我使用带有以下依赖项的factory:
deps: [TagDirective, [ new SkipSelf(), new Optional(), TAG_DIRECTIVES_TOKEN ]]
^^^^^ ^^^^^
current instance of TagDirective parent optional TAG_DIRECTIVES_TOKEN
其中:
-
SkipSelf
告诉angular编译器跳过当前令牌并使用我们在父div[appTag]
中提供的令牌
在这里使用 -
Optional
是因为根div[appTag]
元素无法识别父级TAG_DIRECTIVES_TOKEN
,因此角度编译器不会引发错误:
没有提供InjectionToken标签指令的提供者!
I have a complex scenario which I need help with.
I have a directive (called TagDirective
) that is placed on multiple elements all over my app. I have another directive (QueryDirective
) which needs to reference all instances of TagDirective
that exist on its host element, as well as on all the elements above it in the hierarchy.
Example:
<div appTag="a">
<div appTag="b">
<div appTag="c">
<div appTag="d">
<div appQuery>
<!-- In here I want to have a reference to TagDirectives instances
d,c,b,a -->
</div>
</div>
</div>
<div appTag="e">
<div appTag="f">
<div appTag="g">
<div appTag="h">
<div appQuery>
<!-- In here I want to have a reference to TagDirectives instances
h,g,f,e,b,a -->
</div>
</div>
</div>
<div appQuery>
<!-- In here I want to have a reference to TagDirectives instances
f,e,b,a -->
</div>
</div>
</div>
</div>
</div>
I know I can obtain a reference to the TagDirective
on the host element alone by having the injector provide it in the constructor of QueryDirective
, I also know I can get the next higher instance by injecting ViewContainerRef
and using its parentInjector
member to request an instance of type TagDirective
.
However, I haven't found a way to go further up the tree, and collect all the instances all the way up to the root.
How would I achieve that? Thanks!
Since each of elements has its own injector we can't just use multi: true
it will only work if we provide the same token on the same element.
Possible workaround could be as follows:
export const TAG_DIRECTIVES_TOKEN = new InjectionToken('tags directives');
export function tagDirectiveFactory(dir: TagDirective, token: TagDirective[]) {
return token ? [dir, ...token] : [dir];
}
@Directive({
selector: '[appTag]',
providers: [{
provide: TAG_DIRECTIVES_TOKEN,
useFactory: tagDirectiveFactory,
deps: [TagDirective, [ new SkipSelf(), new Optional(), TAG_DIRECTIVES_TOKEN ]]
}]
})
export class TagDirective {}
@Directive({
selector: '[appQuery]'
})
export class AppQueryDirective {
constructor(@Inject(TAG_DIRECTIVES_TOKEN) private directives: TagDirective[]){
console.log(directives);
}
}
In the code above i am providing TAG_DIRECTIVES_TOKEN
on each of div[appTag]
elements. I use factory with the following dependencies:
deps: [TagDirective, [ new SkipSelf(), new Optional(), TAG_DIRECTIVES_TOKEN ]]
^^^^^ ^^^^^
current instance of TagDirective parent optional TAG_DIRECTIVES_TOKEN
where:
SkipSelf
tells angular compiler to skip current token and use token that we provided in the parentdiv[appTag]
Optional
is used here because rootdiv[appTag]
element can't recognize parentTAG_DIRECTIVES_TOKEN
so angular compiler won't raise the error:
No provider for InjectionToken tags directives!
这篇关于在组件树中获取对特定类型的所有指令的引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!