sercan 3a1a7d44b6 Updated RxJS to 7.4.0
Optimized import paths
2021-11-05 11:36:03 +03:00

187 lines
5.5 KiB
TypeScript

import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnChanges, OnDestroy, OnInit, SimpleChanges } from '@angular/core';
import { NavigationEnd, Router } from '@angular/router';
import { BooleanInput } from '@angular/cdk/coercion';
import { filter, Subject, takeUntil } from 'rxjs';
import { FuseVerticalNavigationComponent } from '@fuse/components/navigation/vertical/vertical.component';
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
import { FuseNavigationItem } from '@fuse/components/navigation/navigation.types';
@Component({
selector : 'fuse-vertical-navigation-aside-item',
templateUrl : './aside.component.html',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class FuseVerticalNavigationAsideItemComponent implements OnChanges, OnInit, OnDestroy
{
/* eslint-disable @typescript-eslint/naming-convention */
static ngAcceptInputType_autoCollapse: BooleanInput;
static ngAcceptInputType_skipChildren: BooleanInput;
/* eslint-enable @typescript-eslint/naming-convention */
@Input() activeItemId: string;
@Input() autoCollapse: boolean;
@Input() item: FuseNavigationItem;
@Input() name: string;
@Input() skipChildren: boolean;
active: boolean = false;
private _fuseVerticalNavigationComponent: FuseVerticalNavigationComponent;
private _unsubscribeAll: Subject<any> = new Subject<any>();
/**
* Constructor
*/
constructor(
private _changeDetectorRef: ChangeDetectorRef,
private _router: Router,
private _fuseNavigationService: FuseNavigationService
)
{
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On changes
*
* @param changes
*/
ngOnChanges(changes: SimpleChanges): void
{
// Active item id
if ( 'activeItemId' in changes )
{
// Mark if active
this._markIfActive(this._router.url);
}
}
/**
* On init
*/
ngOnInit(): void
{
// Mark if active
this._markIfActive(this._router.url);
// Attach a listener to the NavigationEnd event
this._router.events
.pipe(
filter((event): event is NavigationEnd => event instanceof NavigationEnd),
takeUntil(this._unsubscribeAll)
)
.subscribe((event: NavigationEnd) => {
// Mark if active
this._markIfActive(event.urlAfterRedirects);
});
// Get the parent navigation component
this._fuseVerticalNavigationComponent = this._fuseNavigationService.getComponent(this.name);
// Subscribe to onRefreshed on the navigation component
this._fuseVerticalNavigationComponent.onRefreshed.pipe(
takeUntil(this._unsubscribeAll)
).subscribe(() => {
// Mark for check
this._changeDetectorRef.markForCheck();
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next(null);
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Track by function for ngFor loops
*
* @param index
* @param item
*/
trackByFn(index: number, item: any): any
{
return item.id || index;
}
// -----------------------------------------------------------------------------------------------------
// @ Private methods
// -----------------------------------------------------------------------------------------------------
/**
* Check if the given item has the given url
* in one of its children
*
* @param item
* @param currentUrl
* @private
*/
private _hasActiveChild(item: FuseNavigationItem, currentUrl: string): boolean
{
const children = item.children;
if ( !children )
{
return false;
}
for ( const child of children )
{
if ( child.children )
{
if ( this._hasActiveChild(child, currentUrl) )
{
return true;
}
}
// Skip items other than 'basic'
if ( child.type !== 'basic' )
{
continue;
}
// Check if the child has a link and is active
if ( child.link && this._router.isActive(child.link, child.exactMatch || false) )
{
return true;
}
}
return false;
}
/**
* Decide and mark if the item is active
*
* @private
*/
private _markIfActive(currentUrl: string): void
{
// Check if the activeItemId is equals to this item id
this.active = this.activeItemId === this.item.id;
// If the aside has a children that is active,
// always mark it as active
if ( this._hasActiveChild(this.item, currentUrl) )
{
this.active = true;
}
// Mark for check
this._changeDetectorRef.markForCheck();
}
}