coreui-angular-ex-dev
Version:
CoreUI Components Library for Angular
252 lines (223 loc) • 7.32 kB
text/typescript
import { animate, AnimationEvent, state, style, transition, trigger } from '@angular/animations';
import {
NgClass,
NgForOf,
NgIf,
NgStyle,
NgSwitch,
NgSwitchCase,
NgSwitchDefault,
NgTemplateOutlet
} from '@angular/common';
import {
Component,
ElementRef,
forwardRef,
HostBinding,
Input,
OnChanges,
OnDestroy,
OnInit,
Optional,
Renderer2,
SimpleChanges,
ViewChild
} from '@angular/core';
import { NavigationEnd, Router, RouterModule } from '@angular/router';
import { Observable, Subscription } from 'rxjs';
import { filter } from 'rxjs/operators';
import { SidebarService } from '../sidebar.service';
import { SidebarComponent } from '../sidebar/sidebar.component';
import { INavData } from './sidebar-nav';
import { SidebarNavHelper } from './sidebar-nav.service';
import { SidebarNavGroupService } from './sidebar-nav-group.service';
import { HtmlAttributesDirective } from '../../shared';
import { SidebarNavIconPipe } from './sidebar-nav-icon.pipe';
import { SidebarNavBadgePipe } from './sidebar-nav-badge.pipe';
import { SidebarNavLinkComponent } from './sidebar-nav-link.component';
import { SidebarNavLabelComponent } from './sidebar-nav-label.component';
import { SidebarNavTitleComponent } from './sidebar-nav-title.component';
import { SidebarNavDividerComponent } from './sidebar-nav-divider.component';
import { SidebarNavItemClassPipe } from './sidebar-nav-item-class.pipe';
import { IconDirective } from '@coreui/icons-angular';
export class SidebarNavGroupComponent implements OnInit, OnDestroy {
constructor(
private router: Router,
private renderer: Renderer2,
private hostElement: ElementRef,
public helper: SidebarNavHelper,
private sidebarNavGroupService: SidebarNavGroupService
) {
this.navigationEndObservable = router.events.pipe(
filter((event: any) => event instanceof NavigationEnd)
) as Observable<NavigationEnd>;
}
item: any;
dropdownMode: 'path' | 'none' | 'close' = 'path';
show?: boolean;
get hostClasses(): any {
return {
'nav-group': true,
show: this.open
};
}
sidebarNav!: ElementRef;
navigationEndObservable: Observable<NavigationEnd>;
navSubscription!: Subscription;
navGroupSubscription!: Subscription;
public open!: boolean;
public navItems: INavData[] = [];
public display: any = { display: 'block' };
ngOnInit(): void {
this.navItems = [...this.item.children];
this.navSubscription = this.navigationEndObservable.subscribe((event: NavigationEnd) => {
if (this.dropdownMode !== 'none') {
const samePath = this.samePath(event.url);
this.openGroup(samePath);
}
});
if (this.samePath(this.router.routerState.snapshot.url)) {
this.openGroup(true);
}
this.navGroupSubscription = this.sidebarNavGroupService.sidebarNavGroupState$.subscribe(next => {
if (this.dropdownMode === 'close' && next.sidebarNavGroup && next.sidebarNavGroup !== this) {
if (next.sidebarNavGroup.item.url.startsWith(this.item.url)) {
return;
}
if (this.samePath(this.router.routerState.snapshot.url)) {
this.openGroup(true);
return;
}
this.openGroup(false);
}
});
}
samePath(url: string): boolean {
// console.log('item:', this.item.name, this.item.url, 'url:', url);
const itemArray = this.item.url?.split('/');
const urlArray = url.split('/');
return itemArray?.every((value: string, index: number) => {
// console.log(value === urlArray[index], 'value:', value, 'index:', index, urlArray[index], url);
return value === urlArray[index];
});
}
openGroup(open: boolean): void {
this.open = open;
}
toggleGroup($event: any): void {
$event.preventDefault();
this.openGroup(!this.open);
if (this.open) {
this.sidebarNavGroupService.toggle({ open: this.open, sidebarNavGroup: this });
}
}
ngOnDestroy(): void {
this.navSubscription?.unsubscribe();
}
onAnimationStart($event: AnimationEvent) {
this.display = { display: 'block' };
if ($event.toState === 'open') {
const host = this.sidebarNav.nativeElement;
this.renderer.setStyle(host, 'height', `${host['scrollHeight']}px`);
}
}
onAnimationDone($event: AnimationEvent) {
if ($event.toState === 'open') {
const host = this.sidebarNav.nativeElement;
this.renderer.setStyle(host, 'height', 'auto');
}
if ($event.toState === 'closed') {
setTimeout(() => {
this.display = null;
});
}
}
}
export class SidebarNavComponent implements OnChanges {
constructor(
public sidebar: SidebarComponent,
public helper: SidebarNavHelper,
public router: Router,
private renderer: Renderer2,
private hostElement: ElementRef,
private sidebarService: SidebarService
) { }
navItems?: INavData[] = [];
dropdownMode: 'path' | 'none' | 'close' = 'path';
groupItems?: boolean;
compact?: boolean;
get hostClasses(): any {
return {
'sidebar-nav': !this.groupItems,
compact: !this.groupItems && !!this.compact
};
}
get sidebarNavGroupItemsClass(): boolean {
return !!this.groupItems;
}
role = 'nav';
public navItemsArray: INavData[] = [];
public ngOnChanges(changes: SimpleChanges): void {
this.navItemsArray = Array.isArray(this.navItems) ? this.navItems.slice() : [];
}
public hideMobile(): void {
// todo: proper scrollIntoView() after NavigationEnd
if (this.sidebar && this.sidebar.sidebarState.mobile) {
this.sidebarService.toggle({ toggle: 'visible', sidebar: this.sidebar });
}
}
}