2017-08-09 89 views
1

我有一個設置類似如下:父DOM操作由孩子?

<nav> 
    <li> 
     <a someClassToggleDirective>Menu 1</a> <!-- This anchor element toggle determines if ul.sub-menu should be expanded (displayed) --> 
     <ul class="sub-menu"> <!-- This is displayed when it's first sibling 'a' has 'open' class --> 
      <li routerLinkActive="active"><a routerLink="childComp1">Child Component 1</a></li> 
      <li routerLinkActive="active"><a routerLink="childComp2">Child Component 2</a></li> 
      ... 
     </ul> 
    </li> 
    <li> 
     <a someClassToggleDirective>...</a> 
     <ul class="sub-menu"> 
      ... 
     </ul> 
    </li> 
    ... 
</nav> 
<router-outlet></router-outlet> 

加載任何部件,li項目被點擊,然後擴展它的子菜單ul。點擊其中一個子菜單項加載<router-outlet></outlet>中對應的組件,並將子菜單項設置爲激活。例如,路線將是[root]/childComp1。但是,如果我使用瀏覽器的地址欄直接導航到[root]/childComp1,則該組件將被加載,但活動的子組件的父級ul未展開。

那麼,我該如何擴大它?對於要擴展的子菜單(ul),我需要向其兄弟a添加類open。我該怎麼做呢?我想到的一種方法是使用this.router.url來確定組件並根據路由名稱展開相應的sub-menu。但我覺得這不是做這件事的最好方法。有沒有更好的方法?我想避免像jQuery這樣的第三方庫。

+0

您需要爲ul元素添加一個指令,然後在directibe中注入$ location以獲取當前位置,如果它匹配相應的ul元素,那麼我們需要添加類「open」。這將是一個簡單的如果循環,請參閱:[指令獲取位置](https://stackoverflow.com/questions/19139555/is-it-possible-to-get-the-current-location-in-a-directive- in-angular-js) –

+0

@NarenMurali我正在嘗試向'li'添加指令。在'li'裏面是另一個子菜單'ul',其中''li's將具有由'[routerLinkActive]'指令給出的'active'類。因此,在指令中,我想檢查當前'li'中''li'是否有'active'類。如果情況如此,'li'將會有一個'open'類。現在,我會將@ HostListener綁定到什麼事件? 'load'上的綁定將不起作用,因爲到那時所有視圖都不會被初始化。我將如何檢查孩子「li」是否有「主動」課程? –

回答

1

您可以使用修飾器@ContentChildren獲取子菜單內RouterLinkActive的所有實例。並檢測是否存在活動鏈接。

例如,您可以創建指令,該指令保留鏈接列表。並在每條路線上更改toggle expand道具。

指令

import {Directive, HostListener, HostBinding, ContentChildren, QueryList} from '@angular/core'; 
import {Router, RouterLinkActive, NavigationEnd} from '@angular/router'; 
import 'rxjs/Rx'; 
import { Subscription } from 'rxjs/Subscription'; 

@Directive({ selector: '[listToggle]' }) 
export class ListToggleDirective { 

    // Collect RouterLinkActive instances 
    @ContentChildren(RouterLinkActive) links: QueryList<RouterLinkActive>; 

    // If expand=true - show submenu 
    @HostBinding('class.expand') 
    expand: boolean; 

    routerSub: Subscription; 

    constructor(private router: Router) { 

    } 


    ngAfterContentInit(): void { 
    // Detect if there is active links 
    this.routerSub = this.router.events 
     .filter(e => e instanceof NavigationEnd) 
     .subscribe(() => this.detectActiveLink()); 
    } 

    ngOnDestroy(): void { 
    if (this.routerSub) { 
     this.routerSub.unsubscribe(); 
    } 
    } 

    detectActiveLink(): void { 
    setTimeout(() => { 
     const hasActive = this.links.some(link => link.isActive); 
     this.expand = hasActive; 
    }); 
    } 

} 

使用

<ul> 
    <li listToggle> 
     <a>Open menu 1</a> 
     <ul class="sub-menu"> 
      <a routerLink="/cmp1" routerLinkActive="active">cmp1</a> 
      <a routerLink="/cmp2" routerLinkActive="active">cmp2</a> 
     </ul> 
    </li> 
    <li listToggle> 
     <a>Open menu 2</a> 
     <ul class="sub-menu"> 
      <a routerLink="/cmp3" routerLinkActive="active">cmp3</a> 
     </ul> 
    </li> 
</ul> 

樣式

li[listtoggle] { 
    &.expand .sub-menu { 
     display: block; 
    } 
    .sub-menu { 
     display: none; 
    } 
} 

希望這有助於