2017-10-18 33 views
2

我有一個複雜的場景,我需要幫助。獲取組件樹中某個類型的所有指令的引用

我有一個指令(稱爲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類型的實例。

但是,我還沒有找到一種方法去進一步樹,並收集所有的實例一直到根。

我該怎麼做到這一點?謝謝!

+0

我會這樣做一個服務(在provider指令中聲明)。但實際上我對你的問題並不滿意,這對我來說有點不清楚。 – n00dl3

+0

@ n00dl3這意味着該服務將鏡像組件樹結構。我不認爲我想走那麼遠,我的意思是,樹結構已經存在,我只需要找到一種方法來查詢它。你能否試着在問題中明確說明需要澄清的內容? –

+0

解釋爲什麼你想這樣做會有所幫助。 – estus

回答

2

由於每個元素都有自己的注入器,我們不能只使用multi: true,只有當我們在同一元素上提供相同的標記時它纔會起作用。

可能的解決方法可以如下:

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); 
    } 
} 

Stackblitz Example

在上面的代碼我在每個div[appTag]元件提供TAG_DIRECTIVES_TOKEN。我用工廠具有以下依存關係:

deps: [TagDirective, [ new SkipSelf(), new Optional(), TAG_DIRECTIVES_TOKEN ]] 
      ^^^^^           ^^^^^ 
current instance of TagDirective  parent optional TAG_DIRECTIVES_TOKEN 

其中:

  • SkipSelf告訴角度編譯器跳過當前令牌並使用令牌,我們在父div[appTag]

  • Optional提供使用這裏因爲根div[appTag]元素不能識別父親TAG_DIRECTIVES_TOKEN所以角編譯器不會引起錯誤:

No provider for InjectionToken tags directives!

+0

首先,這個作品,謝謝!但是,如果「TagDirective」由第三方庫提供,我無法修改並且不包含該特定提供程序方案,是否有另一種方法?另外,您能否詳細介紹一下'SkipSelf'和'Optional'部分?這些對我來說是新的 –

+0

如果TagDirective由第三方庫提供,請參閱此示例https://stackblitz.com/edit/angular-mrjjn3?file=app/app.component.ts我剛創建了MyTagDirective,它爲我們提供了所有標記 – yurzui

+0

BRILLIANT,您將自己的指令附加到適合其他指令的任何元素!謝謝! :) –

相關問題