@@ -6,21 +6,19 @@ import {
6
6
HostListener ,
7
7
Inject ,
8
8
Input ,
9
- OnChanges ,
10
9
OnDestroy ,
11
10
OnInit ,
12
11
Output ,
13
12
PLATFORM_ID ,
14
- Renderer2 ,
15
- SimpleChanges
13
+ Renderer2
16
14
} from '@angular/core' ;
17
- import { animate , state , style , transition , trigger } from '@angular/animations' ;
15
+ import { DOCUMENT , isPlatformBrowser } from '@angular/common' ;
16
+ import { animate , AnimationEvent , state , style , transition , trigger } from '@angular/animations' ;
18
17
import { BooleanInput , coerceBooleanProperty } from '@angular/cdk/coercion' ;
19
18
import { Subscription } from 'rxjs' ;
20
19
21
- import { OffcanvasService } from '../offcanvas.service' ;
22
20
import { BackdropService } from '../../backdrop/backdrop.service' ;
23
- import { DOCUMENT , isPlatformBrowser } from '@angular/common ' ;
21
+ import { OffcanvasService } from '../offcanvas.service ' ;
24
22
25
23
let nextId = 0 ;
26
24
@@ -29,29 +27,30 @@ let nextId = 0;
29
27
animations : [
30
28
trigger ( 'showHide' , [
31
29
state (
32
- 'true ' ,
30
+ 'visible ' ,
33
31
style ( {
34
- visibility : 'visible'
32
+ // visibility: 'visible'
35
33
} )
36
34
) ,
37
35
state (
38
- 'false ' ,
36
+ 'hidden ' ,
39
37
style ( {
40
- visibility : 'hidden'
38
+ // visibility: 'hidden'
41
39
} )
42
40
) ,
43
- transition ( 'true => false ' , [ animate ( '300ms' ) ] )
41
+ transition ( 'visible < => * ' , [ animate ( '300ms' ) ] )
44
42
] )
45
43
] ,
46
44
templateUrl : './offcanvas.component.html' ,
47
45
styleUrls : [ './offcanvas.component.scss' ] ,
48
46
exportAs : 'cOffcanvas'
49
47
} )
50
- export class OffcanvasComponent implements OnChanges , OnInit , OnDestroy {
48
+ export class OffcanvasComponent implements OnInit , OnDestroy {
49
+
51
50
static ngAcceptInputType_scroll : BooleanInput ;
52
51
53
52
constructor (
54
- @Inject ( DOCUMENT ) private document : any ,
53
+ @Inject ( DOCUMENT ) private document : Document ,
55
54
@Inject ( PLATFORM_ID ) private platformId : any ,
56
55
private renderer : Renderer2 ,
57
56
private hostElement : ElementRef ,
@@ -96,6 +95,7 @@ export class OffcanvasComponent implements OnChanges, OnInit, OnDestroy {
96
95
private _scroll = false ;
97
96
98
97
@Input ( ) id = `offcanvas-${ this . placement } -${ nextId ++ } ` ;
98
+
99
99
/**
100
100
* Default role for offcanvas. [docs]
101
101
* @type string
@@ -113,32 +113,32 @@ export class OffcanvasComponent implements OnChanges, OnInit, OnDestroy {
113
113
/**
114
114
* Toggle the visibility of offcanvas component.
115
115
* @type boolean
116
+ * @default false
116
117
*/
117
118
@Input ( )
118
119
set visible ( value : boolean ) {
119
120
this . _visible = coerceBooleanProperty ( value ) ;
120
- if ( value ) {
121
+ if ( this . _visible ) {
121
122
this . setBackdrop ( this . backdrop ) ;
122
123
this . setFocus ( ) ;
123
124
} else {
124
125
this . setBackdrop ( false ) ;
125
126
}
126
- this . setScroll ( ) ;
127
127
this . visibleChange . emit ( value ) ;
128
128
}
129
129
130
130
get visible ( ) : boolean {
131
131
return this . _visible ;
132
132
}
133
133
134
- private _visible ! : boolean ;
134
+ private _visible : boolean = false ;
135
135
136
136
/**
137
137
* Event triggered on visible change.
138
138
*/
139
139
@Output ( ) visibleChange = new EventEmitter < boolean > ( ) ;
140
140
141
- private activeBackdrop ! : any ;
141
+ private activeBackdrop ! : HTMLDivElement ;
142
142
private scrollbarWidth ! : string ;
143
143
144
144
private stateToggleSubscription ! : Subscription ;
@@ -149,7 +149,7 @@ export class OffcanvasComponent implements OnChanges, OnInit, OnDestroy {
149
149
return {
150
150
offcanvas : true ,
151
151
[ `offcanvas-${ this . placement } ` ] : ! ! this . placement ,
152
- show : this . visible
152
+ show : this . show
153
153
} ;
154
154
}
155
155
@@ -164,8 +164,47 @@ export class OffcanvasComponent implements OnChanges, OnInit, OnDestroy {
164
164
}
165
165
166
166
@HostBinding ( '@showHide' )
167
- get animateType ( ) : boolean {
168
- return this . visible ;
167
+ get animateTrigger ( ) : string {
168
+ return this . visible ? 'visible' : 'hidden' ;
169
+ }
170
+
171
+ get show ( ) : boolean {
172
+ return this . visible && this . _show ;
173
+ }
174
+
175
+ set show ( value : boolean ) {
176
+ this . _show = value ;
177
+ }
178
+
179
+ private _show = false ;
180
+
181
+ @HostListener ( '@showHide.start' , [ '$event' ] )
182
+ animateStart ( event : AnimationEvent ) {
183
+ const scrollbarWidth = this . scrollbarWidth ;
184
+ if ( event . toState === 'visible' ) {
185
+ if ( ! this . scroll ) {
186
+ this . renderer . setStyle ( this . document . body , 'overflow' , 'hidden' ) ;
187
+ this . renderer . setStyle ( this . document . body , 'padding-right' , scrollbarWidth ) ;
188
+ }
189
+ this . renderer . addClass ( this . hostElement . nativeElement , 'showing' ) ;
190
+ } else {
191
+ this . renderer . addClass ( this . hostElement . nativeElement , 'hiding' ) ;
192
+ }
193
+ }
194
+
195
+ @HostListener ( '@showHide.done' , [ '$event' ] )
196
+ animateDone ( event : AnimationEvent ) {
197
+ setTimeout ( ( ) => {
198
+ if ( event . toState === 'visible' ) {
199
+ this . renderer . removeClass ( this . hostElement . nativeElement , 'showing' ) ;
200
+ }
201
+ if ( event . toState === 'hidden' ) {
202
+ this . renderer . removeClass ( this . hostElement . nativeElement , 'hiding' ) ;
203
+ this . renderer . removeStyle ( this . document . body , 'overflow' ) ;
204
+ this . renderer . removeStyle ( this . document . body , 'paddingRight' ) ;
205
+ }
206
+ } ) ;
207
+ this . show = this . visible ;
169
208
}
170
209
171
210
@HostListener ( 'document:keydown' , [ '$event' ] )
@@ -181,22 +220,17 @@ export class OffcanvasComponent implements OnChanges, OnInit, OnDestroy {
181
220
}
182
221
183
222
ngOnInit ( ) : void {
184
- this . setScroll ( ) ;
185
223
this . scrollbarWidth = this . backdropService . scrollbarWidth ;
186
224
this . stateToggleSubscribe ( ) ;
225
+ // hotfix to avoid end offcanvas flicker on first render
226
+ this . renderer . setStyle ( this . hostElement . nativeElement , 'display' , 'flex' ) ;
187
227
}
188
228
189
229
ngOnDestroy ( ) : void {
190
230
this . offcanvasService . toggle ( { show : false , id : this . id } ) ;
191
231
this . stateToggleSubscribe ( false ) ;
192
232
}
193
233
194
- ngOnChanges ( changes : SimpleChanges ) : void {
195
- if ( changes [ 'scroll' ] ) {
196
- this . setScroll ( ) ;
197
- }
198
- }
199
-
200
234
private stateToggleSubscribe ( subscribe : boolean = true ) : void {
201
235
if ( subscribe ) {
202
236
this . stateToggleSubscription =
@@ -237,18 +271,4 @@ export class OffcanvasComponent implements OnChanges, OnInit, OnDestroy {
237
271
setTimeout ( ( ) => this . hostElement . nativeElement . focus ( ) ) ;
238
272
}
239
273
}
240
-
241
- setScroll ( ) {
242
- if ( this . visible ) {
243
- if ( ! this . scroll ) {
244
- this . renderer . setStyle ( this . document . body , 'overflow' , 'hidden' ) ;
245
- this . renderer . setStyle ( this . document . body , 'paddingRight.px' , '0' ) ;
246
- }
247
- return ;
248
- }
249
- if ( ! this . scroll ) {
250
- this . renderer . removeStyle ( this . document . body , 'overflow' ) ;
251
- this . renderer . removeStyle ( this . document . body , 'paddingRight' ) ;
252
- }
253
- }
254
274
}
0 commit comments