我试着做一个有角度路径的嵌套菜单。
我需要的是将类应用到嵌套路由(如果它是活动的),并将类应用到父组件(如果其子组件是活动的)。
我怎样才能做到这一点?现在,我正在进行递归菜单构建,以便在需要多级嵌套时使用方便。
component.html
<a (click)="toggleActive()" [class.active]="isActive" [routerLink]="menuItem.link" *ngIf="menuItem.link; else noLink">
<i *ngIf="menuItem.faClass" class="fa fa-{{menuItem.faClass}}"></i>
{{menuItem.name}} <span *ngIf="menuItem.children && menuItem.children.length > 0" class="fa fa-chevron-down"></span>
</a>
<ng-container *ngIf="menuItem.children && menuItem.children.length > 0">
<ul class="nav child_menu" [class.active]="isActive" routerLinkActive="active"
*ngFor="let item of menuItem.children">
<li menu-item [menuItem]="item" (checkActive)="updateActiveState()"></li>
</ul>
</ng-container>
<ng-template #noLink>
<a (click)="toggleActive()" [class.active]="isActive">
<i *ngIf="menuItem.faClass" class="fa fa-{{menuItem.faClass}}"></i>
{{menuItem.name}} <span *ngIf="menuItem.children && menuItem.children.length > 0" class="fa fa-chevron-down"></span>
</a>
</ng-template>component.ts
@Component({
selector: '[menu-item]',
templateUrl: './menu-item.component.html',
styleUrls: ['./menu-item.component.scss'],
host: {
'[class.active]': 'hostActive && isActive',
'[class.active-sm]': 'hostActiveSm && isActive'
}
})
export class MenuItemComponent implements OnInit, AfterViewInit, OnChanges {
public menuSize;
public isActive = false;
@Input() menuItem: MenuItem;
@Output() checkActive: EventEmitter<void> = new EventEmitter<void>();
@ViewChild(MenuItemComponent) menuComponent: MenuItemComponent;
private hostActive = true;
private hostActiveSm = false;
@HostBinding('class') hostClass = this.hostActive && this.isActive ? 'active' : this.hostActiveSm && this.isActive ? 'active-sm' : '';
constructor(
private router: Router,
private uss: UiStateService,
) {
}
ngOnInit() {
this.uss.menuSubject.subscribe(msg => {
this.menuSize = msg;
if (this.menuSize === MenuSizes.sm) {
this.hostActive = false;
this.hostActiveSm = true;
} else {
this.hostActive = true;
this.hostActiveSm = false;
}
this.updateActiveState();
});
this.router.events.subscribe((e: Event) => {
if (e instanceof NavigationEnd) {
this.updateActiveState();
}
});
}
ngOnChanges() {
}
ngAfterViewInit() {
this.updateActiveState();
}
public toggleActive(): void {
this.isActive = !this.isActive;
// if (this.menuComponent) {
// this.menuComponent.isActive = true;
// }
}
private updateActiveState(): void {
// reset previous state
this.isActive = false;
if (this.menuComponent) {
this.menuComponent.isActive = false;
}
// Check state of item with no els
const url = this.router.url;
console.log('URL', url, 'Menu link', this.menuItem.link);
console.log(url.match('/' + this.menuItem.link + '$/'));
if (this.menuItem && this.menuItem.link && url.match('/' + this.menuItem.link + '$/')) {
this.isActive = true;
this.checkActive.emit();
}
if (this.menuComponent) {
console.log('Menu component');
console.log(this.menuComponent, this.menuComponent.menuItem.link);
this.isActive = true;
}
}
}是否有方法从组件中知道它的路由是否是活动的?诀窍是,我使用的是[routerLink],而不是routerLink,这样我就可以将.作为根页面的链接传递。
更新
尽我所能再现stackblitz,试着访问"Dasboard“。它应该向父li添加一个“活动”类。如果您自己添加它,您将看到它的元素上的应用类和右边的一个有色条。
发布于 2018-11-25 14:57:12
我设法解决了这个问题。StackBlitz
主要是通过在setTimeOut事件中没有时间地使用navigateEnd来实现的,这样我就可以检查isActive的状态并获得值(如果没有setTimeout,则值是“从过去”得到的,意思是在取值时没有更新)。它的工作方式有点棘手,但却很有效。
发布于 2018-11-19 09:22:21
也许您可以尝试在任何组件中访问ActivatedRoute。
import { Router, ActivatedRoute} from '@angular/router';
constructor(private router: Router, private activatedRoute:ActivatedRoute) {
console.log(activatedRoute.snapshot.url) // array of states
console.log(activatedRoute.snapshot.url[0].path)
}希望这会有帮助!
发布于 2018-11-21 18:52:07
所有这些功能都是内置在角的路由器模块中的。这就是儿童路线背后的全部想法。如果一个路由是真正的父组件,那么它应该是路由中的父组件。通过这样做,您可以简单地检查父路由是否是活动的,而不是应用程序组件中任意分配的任何路由。
此外,这有一个巨大的好处,就是允许仪表板简单地路由到['../sibling']。
在我的子路由(特别是/home/home. that )中,您将看到一个注释行,它将使仪表板能够自动加载(如果这是所需的行为)。
您已经在动态菜单项中使用了routerLinkActive,但是要有最直接的方法,它应该在绑定到routerLink的项上,如概述的这里。
您可能会遇到的最大问题是,嵌套的routerLink元素并不像这个问题中讨论的那样很好地在DOM中发挥作用,因此您需要停止传播。
app-component.html
<ul app-menu-item
class="nav side-menu"
[menu]="menu">
</ul>菜单-item.html:
<li
*ngFor="let item of menu"
[routerLink]="item.link"
routerLinkActive="active"
(click)="stop($event)">
{{item.name}}
<ul app-menu-item
*ngIf="item.children"
class="nav side-menu"
[menu]="item.children">
</ul>
</li>虽然它没有回答问题中的标题,但我将补充说,这个问题最容易通过使用父路由来解决,然后按如下方式设置menu-item.html:
<li *ngFor="let item of menu">
<a [routerLink]="item.link" routerLinkActive="active">
{{item.name}}
</a>
<ul class="nav side-menu"
*ngIf="item.children"
app-menu-item [menu]="item.children">
</ul>
</li>然后使用scss中的同级选择器显示或隐藏菜单。
https://stackoverflow.com/questions/53299952
复制相似问题