(FuseNavigation) Moved the changeDetection strategy to OnPush to improve the performance and allow for huge amounts of navigation items

(FuseNavigation) Use service to update the menu items
(FuseNavigationDocs) Updated the docs
This commit is contained in:
sercan 2018-10-08 12:36:15 +03:00
parent 63bd95ea1e
commit ab7bd882a0
7 changed files with 309 additions and 43 deletions

View File

@ -1,4 +1,4 @@
import { Component, Input, OnInit, ViewEncapsulation } from '@angular/core';
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnInit, ViewEncapsulation } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@ -8,7 +8,8 @@ import { FuseNavigationService } from '@fuse/components/navigation/navigation.se
selector : 'fuse-navigation',
templateUrl : './navigation.component.html',
styleUrls : ['./navigation.component.scss'],
encapsulation: ViewEncapsulation.None
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class FuseNavigationComponent implements OnInit
{
@ -22,9 +23,12 @@ export class FuseNavigationComponent implements OnInit
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*
* @param {ChangeDetectorRef} _changeDetectorRef
* @param {FuseNavigationService} _fuseNavigationService
*/
constructor(
private _changeDetectorRef: ChangeDetectorRef,
private _fuseNavigationService: FuseNavigationService
)
{
@ -48,7 +52,39 @@ export class FuseNavigationComponent implements OnInit
this._fuseNavigationService.onNavigationChanged
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(() => {
// Load the navigation
this.navigation = this._fuseNavigationService.getCurrentNavigation();
// Mark for check
this._changeDetectorRef.markForCheck();
});
// Subscribe to navigation item additions
this._fuseNavigationService.onNavigationItemAdded
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(() => {
// Mark for check
this._changeDetectorRef.markForCheck();
});
// Subscribe to navigation item updates
this._fuseNavigationService.onNavigationItemUpdated
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(() => {
// Mark for check
this._changeDetectorRef.markForCheck();
});
// Subscribe to navigation item removal
this._fuseNavigationService.onNavigationItemRemoved
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(() => {
// Mark for check
this._changeDetectorRef.markForCheck();
});
}
}

View File

@ -1,5 +1,6 @@
import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable, Subject } from 'rxjs';
import * as _ from 'lodash';
import { FuseNavigationItem } from '@fuse/types';
@ -15,6 +16,9 @@ export class FuseNavigationService
private _onNavigationChanged: BehaviorSubject<any>;
private _onNavigationRegistered: BehaviorSubject<any>;
private _onNavigationUnregistered: BehaviorSubject<any>;
private _onNavigationItemAdded: BehaviorSubject<any>;
private _onNavigationItemUpdated: BehaviorSubject<any>;
private _onNavigationItemRemoved: BehaviorSubject<any>;
private _currentNavigationKey: string;
private _registry: { [key: string]: any } = {};
@ -33,6 +37,9 @@ export class FuseNavigationService
this._onNavigationChanged = new BehaviorSubject(null);
this._onNavigationRegistered = new BehaviorSubject(null);
this._onNavigationUnregistered = new BehaviorSubject(null);
this._onNavigationItemAdded = new BehaviorSubject(null);
this._onNavigationItemUpdated = new BehaviorSubject(null);
this._onNavigationItemRemoved = new BehaviorSubject(null);
}
// -----------------------------------------------------------------------------------------------------
@ -69,6 +76,36 @@ export class FuseNavigationService
return this._onNavigationUnregistered.asObservable();
}
/**
* Get onNavigationItemAdded
*
* @returns {Observable<any>}
*/
get onNavigationItemAdded(): Observable<any>
{
return this._onNavigationItemAdded.asObservable();
}
/**
* Get onNavigationItemUpdated
*
* @returns {Observable<any>}
*/
get onNavigationItemUpdated(): Observable<any>
{
return this._onNavigationItemUpdated.asObservable();
}
/**
* Get onNavigationItemRemoved
*
* @returns {Observable<any>}
*/
get onNavigationItemRemoved(): Observable<any>
{
return this._onNavigationItemRemoved.asObservable();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
@ -319,6 +356,33 @@ export class FuseNavigationService
// Add the item
parent.children.push(item);
}
// Trigger the observable
this._onNavigationItemAdded.next(true);
}
/**
* Update navigation item with the given id
*
* @param id
* @param properties
*/
updateNavigationItem(id, properties): void
{
// Get the navigation item
const navigationItem = this.getNavigationItem(id);
// If there is no navigation with the give id, return
if ( !navigationItem )
{
return;
}
// Merge the navigation properties
_.merge(navigationItem, properties);
// Trigger the observable
this._onNavigationItemUpdated.next(true);
}
/**
@ -346,5 +410,8 @@ export class FuseNavigationService
// Remove the item
parent.splice(parent.indexOf(item), 1);
// Trigger the observable
this._onNavigationItemRemoved.next(true);
}
}

View File

@ -1,4 +1,4 @@
import { Component, HostBinding, Input, OnDestroy, OnInit } from '@angular/core';
import { ChangeDetectorRef, Component, HostBinding, Input, OnDestroy, OnInit } from '@angular/core';
import { NavigationEnd, Router } from '@angular/router';
import { Subject } from 'rxjs';
import { filter, takeUntil } from 'rxjs/operators';
@ -30,10 +30,12 @@ export class FuseNavVerticalCollapsableComponent implements OnInit, OnDestroy
/**
* Constructor
*
* @param {ChangeDetectorRef} _changeDetectorRef
* @param {FuseNavigationService} _fuseNavigationService
* @param {Router} _router
*/
constructor(
private _changeDetectorRef: ChangeDetectorRef,
private _fuseNavigationService: FuseNavigationService,
private _router: Router
)
@ -111,6 +113,33 @@ export class FuseNavVerticalCollapsableComponent implements OnInit, OnDestroy
{
this.collapse();
}
// Subscribe to navigation item additions
this._fuseNavigationService.onNavigationItemAdded
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(() => {
// Mark for check
this._changeDetectorRef.markForCheck();
});
// Subscribe to navigation item updates
this._fuseNavigationService.onNavigationItemUpdated
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(() => {
// Mark for check
this._changeDetectorRef.markForCheck();
});
// Subscribe to navigation item removal
this._fuseNavigationService.onNavigationItemRemoved
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(() => {
// Mark for check
this._changeDetectorRef.markForCheck();
});
}
/**
@ -154,6 +183,10 @@ export class FuseNavVerticalCollapsableComponent implements OnInit, OnDestroy
}
this.isOpen = true;
// Mark for check
this._changeDetectorRef.markForCheck();
this._fuseNavigationService.onItemCollapseToggled.next();
}
@ -168,6 +201,10 @@ export class FuseNavVerticalCollapsableComponent implements OnInit, OnDestroy
}
this.isOpen = false;
// Mark for check
this._changeDetectorRef.markForCheck();
this._fuseNavigationService.onItemCollapseToggled.next();
}

View File

@ -1,13 +1,16 @@
import { Component, HostBinding, Input } from '@angular/core';
import { ChangeDetectorRef, Component, HostBinding, Input, OnDestroy, OnInit } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { FuseNavigationItem } from '@fuse/types';
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
@Component({
selector : 'fuse-nav-vertical-group',
templateUrl: './group.component.html',
styleUrls : ['./group.component.scss']
})
export class FuseNavVerticalGroupComponent
export class FuseNavVerticalGroupComponent implements OnInit, OnDestroy
{
@HostBinding('class')
classes = 'nav-group nav-item';
@ -15,11 +18,72 @@ export class FuseNavVerticalGroupComponent
@Input()
item: FuseNavigationItem;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*/
constructor()
/**
*
* @param {ChangeDetectorRef} _changeDetectorRef
* @param {FuseNavigationService} _fuseNavigationService
*/
constructor(
private _changeDetectorRef: ChangeDetectorRef,
private _fuseNavigationService: FuseNavigationService
)
{
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
// Subscribe to navigation item additions
this._fuseNavigationService.onNavigationItemAdded
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(() => {
// Mark for check
this._changeDetectorRef.markForCheck();
});
// Subscribe to navigation item updates
this._fuseNavigationService.onNavigationItemUpdated
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(() => {
// Mark for check
this._changeDetectorRef.markForCheck();
});
// Subscribe to navigation item removal
this._fuseNavigationService.onNavigationItemRemoved
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(() => {
// Mark for check
this._changeDetectorRef.markForCheck();
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
}

View File

@ -1,13 +1,16 @@
import { Component, HostBinding, Input } from '@angular/core';
import { ChangeDetectorRef, Component, HostBinding, Input, OnDestroy, OnInit } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { FuseNavigationItem } from '@fuse/types';
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
@Component({
selector : 'fuse-nav-vertical-item',
templateUrl: './item.component.html',
styleUrls : ['./item.component.scss']
})
export class FuseNavVerticalItemComponent
export class FuseNavVerticalItemComponent implements OnInit, OnDestroy
{
@HostBinding('class')
classes = 'nav-item';
@ -15,10 +18,71 @@ export class FuseNavVerticalItemComponent
@Input()
item: FuseNavigationItem;
// Private
private _unsubscribeAll: Subject<any>;
/**
* Constructor
*/
constructor()
/**
*
* @param {ChangeDetectorRef} _changeDetectorRef
* @param {FuseNavigationService} _fuseNavigationService
*/
constructor(
private _changeDetectorRef: ChangeDetectorRef,
private _fuseNavigationService: FuseNavigationService
)
{
// Set the private defaults
this._unsubscribeAll = new Subject();
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void
{
// Subscribe to navigation item additions
this._fuseNavigationService.onNavigationItemAdded
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(() => {
// Mark for check
this._changeDetectorRef.markForCheck();
});
// Subscribe to navigation item updates
this._fuseNavigationService.onNavigationItemUpdated
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(() => {
// Mark for check
this._changeDetectorRef.markForCheck();
});
// Subscribe to navigation item removal
this._fuseNavigationService.onNavigationItemRemoved
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(() => {
// Mark for check
this._changeDetectorRef.markForCheck();
});
}
/**
* On destroy
*/
ngOnDestroy(): void
{
// Unsubscribe from all subscriptions
this._unsubscribeAll.next();
this._unsubscribeAll.complete();
}
}

View File

@ -3,7 +3,7 @@
<!-- HEADER -->
<div class="header accent p-24 h-160" fxLayout="row" fxLayoutAlign="start center">
<div fxLayout="column" fxLayoutAlign="center start">
<div class="black-fg" fxLayout="row" fxLayoutAlign="start center">
<div fxLayout="row" fxLayoutAlign="start center">
<mat-icon class="secondary-text s-18">home</mat-icon>
<mat-icon class="secondary-text s-16">chevron_right</mat-icon>
<span class="secondary-text">Documentation</span>
@ -187,12 +187,13 @@
showHideCalendarMenuItem(): void
{
// Get the calendar item from the navigation
const calendarNavItem = this._fuseNavigationService.getNavigationItem('calendar');
// Toggle the visibility
this.hidden = !this.hidden;
calendarNavItem.hidden = this.hidden;
// Update the calendar menu item
this._fuseNavigationService.updateNavigationItem('calendar', {
hidden: this.hidden
});
}
</textarea>
</fuse-highlight>
@ -211,11 +212,12 @@
<textarea #source>
updateMailBadge()
{
// Get the mail nav item
const mailNavItem = this._fuseNavigationService.getNavigationItem('mail');
// Update the badge title
mailNavItem.badge.title = 35;
this._fuseNavigationService.updateNavigationItem('mail', {
badge: {
title: 35
}
});
}
</textarea>
</fuse-highlight>
@ -242,14 +244,12 @@
url : '/apps/calendar'
};
// Get the calendar item from the navigation
const calendarNavItem = this._fuseNavigationService.getNavigationItem('calendar');
// Make the calendar navigation item collapsable
calendarNavItem.type = 'collapse';
// Add the navigation item
this._fuseNavigationService.addNavigationItem(newNavItem, 'calendar');
this._fuseNavigationService.updateNavigationItem('calendar', {
type: 'collapsable',
children: [
newNavItem
]
});
}
</textarea>
</fuse-highlight>

View File

@ -32,12 +32,13 @@ export class DocsComponentsNavigationComponent
*/
showHideCalendarMenuItem(): void
{
// Get the calendar item from the navigation
const calendarNavItem = this._fuseNavigationService.getNavigationItem('calendar');
// Toggle the visibility
this.hidden = !this.hidden;
calendarNavItem.hidden = this.hidden;
// Update the calendar menu item
this._fuseNavigationService.updateNavigationItem('calendar', {
hidden: this.hidden
});
}
/**
@ -45,11 +46,10 @@ export class DocsComponentsNavigationComponent
*/
updateMailBadge(): void
{
// Get the mail nav item
const mailNavItem = this._fuseNavigationService.getNavigationItem('mail');
// Update the badge title
mailNavItem.badge.title = 35;
this._fuseNavigationService.updateNavigationItem('02001', {
title: 'Transactionssss'
});
}
/**
@ -65,14 +65,12 @@ export class DocsComponentsNavigationComponent
url : '/apps/calendar'
};
// Get the calendar item from the navigation
const calendarNavItem = this._fuseNavigationService.getNavigationItem('calendar');
// Make the calendar navigation item collapsable
calendarNavItem.type = 'collapsable';
// Add the navigation item
this._fuseNavigationService.addNavigationItem(newNavItem, 'calendar');
this._fuseNavigationService.updateNavigationItem('calendar', {
type: 'collapsable',
children: [
newNavItem
]
});
}
/**