@@ -16,8 +16,8 @@ import {
16
16
OnInit ,
17
17
Output ,
18
18
} from '@angular/core' ;
19
- import { Subject } from 'rxjs' ;
20
- import { takeUntil , filter } from 'rxjs/operators' ;
19
+ import { combineLatest , Subject } from 'rxjs' ;
20
+ import { takeUntil , filter , map , startWith } from 'rxjs/operators' ;
21
21
22
22
import { convertToBoolProperty , NbBooleanInput } from '../helpers' ;
23
23
import { NbThemeService } from '../../services/theme.service' ;
@@ -146,6 +146,7 @@ export class NbSidebarFooterComponent {
146
146
} )
147
147
export class NbSidebarComponent implements OnInit , OnDestroy {
148
148
149
+ protected readonly responsiveValueChange$ : Subject < boolean > = new Subject < boolean > ( ) ;
149
150
protected responsiveState : NbSidebarResponsiveState = 'pc' ;
150
151
151
152
protected destroy$ = new Subject < void > ( ) ;
@@ -254,7 +255,7 @@ export class NbSidebarComponent implements OnInit, OnDestroy {
254
255
set state ( value : NbSidebarState ) {
255
256
this . _state = value ;
256
257
}
257
- protected _state : NbSidebarState ;
258
+ protected _state : NbSidebarState = 'expanded' ;
258
259
259
260
/**
260
261
* Makes sidebar listen to media query events and change its behaviour
@@ -265,7 +266,10 @@ export class NbSidebarComponent implements OnInit, OnDestroy {
265
266
return this . _responsive ;
266
267
}
267
268
set responsive ( value : boolean ) {
268
- this . _responsive = convertToBoolProperty ( value ) ;
269
+ if ( this . responsive !== convertToBoolProperty ( value ) ) {
270
+ this . _responsive = ! this . responsive ;
271
+ this . responsiveValueChange$ . next ( this . responsive ) ;
272
+ }
269
273
}
270
274
protected _responsive : boolean = false ;
271
275
static ngAcceptInputType_responsive : NbBooleanInput ;
@@ -344,13 +348,26 @@ export class NbSidebarComponent implements OnInit, OnDestroy {
344
348
. subscribe ( ( ) => this . compact ( ) ) ;
345
349
346
350
getSidebarState$
347
- . pipe ( filter ( ( { tag } ) => ! this . tag || this . tag === tag ) )
351
+ . pipe (
352
+ filter ( ( { tag } ) => ! this . tag || this . tag === tag ) ,
353
+ takeUntil ( this . destroy$ ) ,
354
+ )
348
355
. subscribe ( ( { observer } ) => observer . next ( this . state ) ) ;
349
356
350
357
getSidebarResponsiveState$
351
- . pipe ( filter ( ( { tag } ) => ! this . tag || this . tag === tag ) )
358
+ . pipe (
359
+ filter ( ( { tag } ) => ! this . tag || this . tag === tag ) ,
360
+ takeUntil ( this . destroy$ ) ,
361
+ )
352
362
. subscribe ( ( { observer } ) => observer . next ( this . responsiveState ) ) ;
353
363
364
+ this . responsiveValueChange$
365
+ . pipe (
366
+ filter ( ( responsive : boolean ) => ! responsive ) ,
367
+ takeUntil ( this . destroy$ ) ,
368
+ )
369
+ . subscribe ( ( ) => this . expand ( ) ) ;
370
+
354
371
this . subscribeToMediaQueryChange ( ) ;
355
372
}
356
373
@@ -376,27 +393,21 @@ export class NbSidebarComponent implements OnInit, OnDestroy {
376
393
* Collapses the sidebar
377
394
*/
378
395
collapse ( ) {
379
- this . state = 'collapsed' ;
380
- this . stateChange . emit ( this . state ) ;
381
- this . cd . markForCheck ( ) ;
396
+ this . updateState ( 'collapsed' ) ;
382
397
}
383
398
384
399
/**
385
400
* Expands the sidebar
386
401
*/
387
402
expand ( ) {
388
- this . state = 'expanded' ;
389
- this . stateChange . emit ( this . state ) ;
390
- this . cd . markForCheck ( ) ;
403
+ this . updateState ( 'expanded' ) ;
391
404
}
392
405
393
406
/**
394
407
* Compacts the sidebar (minimizes)
395
408
*/
396
409
compact ( ) {
397
- this . state = 'compacted' ;
398
- this . stateChange . emit ( this . state ) ;
399
- this . cd . markForCheck ( ) ;
410
+ this . updateState ( 'compacted' ) ;
400
411
}
401
412
402
413
/**
@@ -418,18 +429,20 @@ export class NbSidebarComponent implements OnInit, OnDestroy {
418
429
}
419
430
420
431
if ( this . state === 'compacted' || this . state === 'collapsed' ) {
421
- this . state = 'expanded' ;
432
+ this . updateState ( 'expanded' ) ;
422
433
} else {
423
- this . state = compact ? 'compacted' : 'collapsed' ;
434
+ this . updateState ( compact ? 'compacted' : 'collapsed' ) ;
424
435
}
425
- this . stateChange . emit ( this . state ) ;
426
- this . cd . markForCheck ( ) ;
427
436
}
428
437
429
438
protected subscribeToMediaQueryChange ( ) {
430
- this . themeService . onMediaQueryChange ( )
439
+ combineLatest ( [
440
+ this . responsiveValueChange$ . pipe ( startWith ( this . responsive ) ) ,
441
+ this . themeService . onMediaQueryChange ( ) ,
442
+ ] )
431
443
. pipe (
432
- filter ( ( ) => this . responsive ) ,
444
+ filter ( ( [ responsive ] ) => responsive ) ,
445
+ map ( ( [ , breakpoints ] ) => breakpoints ) ,
433
446
takeUntil ( this . destroy$ ) ,
434
447
)
435
448
. subscribe ( ( [ prev , current ] : [ NbMediaBreakpoint , NbMediaBreakpoint ] ) => {
@@ -449,7 +462,7 @@ export class NbSidebarComponent implements OnInit, OnDestroy {
449
462
this . collapse ( ) ;
450
463
newResponsiveState = 'mobile' ;
451
464
}
452
- if ( ! isCollapsed && ! isCompacted && prev . width < current . width ) {
465
+ if ( ! isCollapsed && ! isCompacted && ( ! prev . width || prev . width < current . width ) ) {
453
466
this . expand ( ) ;
454
467
this . fixed = false ;
455
468
newResponsiveState = 'pc' ;
@@ -475,6 +488,14 @@ export class NbSidebarComponent implements OnInit, OnDestroy {
475
488
return this . getMenuLink ( element . parentElement ) ;
476
489
}
477
490
491
+ protected updateState ( state : NbSidebarState ) : void {
492
+ if ( this . state !== state ) {
493
+ this . state = state ;
494
+ this . stateChange . emit ( this . state ) ;
495
+ this . cd . markForCheck ( ) ;
496
+ }
497
+ }
498
+
478
499
/**
479
500
* @deprecated Use `responsive` property instead
480
501
* @breaking -change Remove @8.0.0
0 commit comments