@@ -14,9 +14,15 @@ import {
1414} from '@angular/core' ;
1515import { AnimationBuilder , AnimationPlayer , useAnimation } from '@angular/animations' ;
1616
17- import { collapseAnimation , expandAnimation } from './collapse.animations' ;
1817import { BooleanInput , coerceBooleanProperty } from '@angular/cdk/coercion' ;
1918
19+ import {
20+ collapseAnimation ,
21+ collapseHorizontalAnimation ,
22+ expandAnimation ,
23+ expandHorizontalAnimation
24+ } from './collapse.animations' ;
25+
2026// todo
2127// tslint:disable-next-line:no-conflicting-lifecycle
2228@Directive ( {
@@ -25,6 +31,7 @@ import { BooleanInput, coerceBooleanProperty } from '@angular/cdk/coercion';
2531} )
2632export class CollapseDirective implements OnChanges , OnDestroy , DoCheck , AfterViewInit {
2733
34+ static ngAcceptInputType_horizontal : BooleanInput ;
2835 static ngAcceptInputType_navbar : BooleanInput ;
2936
3037 private _animate = true ;
@@ -39,6 +46,18 @@ export class CollapseDirective implements OnChanges, OnDestroy, DoCheck, AfterVi
3946 return this . _animate ;
4047 }
4148
49+ /**
50+ * Set horizontal collapsing to transition the width instead of height.
51+ */
52+ @Input ( )
53+ set horizontal ( value : boolean ) {
54+ this . _horizontal = coerceBooleanProperty ( value ) ;
55+ }
56+ get horizontal ( ) : boolean {
57+ return this . _horizontal ;
58+ }
59+ private _horizontal : boolean = false ;
60+
4261 private _visible = false ;
4362 /**
4463 * Toggle the visibility of collapsible element.
@@ -66,11 +85,11 @@ export class CollapseDirective implements OnChanges, OnDestroy, DoCheck, AfterVi
6685 /**
6786 * @ignore
6887 */
69- @Input ( ) duration = '400ms ' ;
88+ @Input ( ) duration = '350ms ' ;
7089 /**
7190 * @ignore
7291 */
73- @Input ( ) transition = 'ease-in-out ' ;
92+ @Input ( ) transition = 'ease' ;
7493 /**
7594 * Event emitted on visibility change. [docs]
7695 * @type string
@@ -79,32 +98,45 @@ export class CollapseDirective implements OnChanges, OnDestroy, DoCheck, AfterVi
7998
8099 private player ! : AnimationPlayer ;
81100 private readonly host : HTMLElement ;
101+ private scrollHeight ! : number ;
102+ private scrollWidth ! : number ;
103+ private collapsing : boolean = false ;
82104
83105 constructor (
84106 private hostElement : ElementRef ,
85107 private renderer : Renderer2 ,
86108 private animationBuilder : AnimationBuilder
87109 ) {
88110 this . host = this . hostElement . nativeElement ;
89- this . renderer . setStyle ( this . host , 'display' , 'none' ) ;
111+ this . setDisplay ( false ) ;
90112 }
91113
92114 @HostBinding ( 'class' )
93115 get hostClasses ( ) : any {
94116 return {
95117 'navbar-collapse' : this . navbar ,
96- show : this . visible
118+ show : this . visible ,
119+ 'collapse-horizontal' : this . horizontal ,
120+ collapsing : this . collapsing
121+ // collapse: !this.collapsing
97122 } ;
98123 }
99124
125+ ngAfterViewInit ( ) : void {
126+ if ( this . visible ) {
127+ this . toggle ( ) ;
128+ }
129+ }
130+
100131 ngOnDestroy ( ) : void {
101132 this . destroyPlayer ( ) ;
102133 }
103134
104135 ngOnChanges ( changes : SimpleChanges ) : void {
105136 if ( changes [ 'visible' ] ) {
106- // tslint:disable-next-line:no-unused-expression
107- ( ! changes [ 'visible' ] . firstChange || ! changes [ 'visible' ] . currentValue ) && this . toggle ( changes [ 'visible' ] . currentValue ) ;
137+ if ( ! changes [ 'visible' ] . firstChange || ! changes [ 'visible' ] . currentValue ) {
138+ this . toggle ( changes [ 'visible' ] . currentValue ) ;
139+ }
108140 }
109141 }
110142
@@ -115,39 +147,57 @@ export class CollapseDirective implements OnChanges, OnDestroy, DoCheck, AfterVi
115147 }
116148
117149 toggle ( visible = this . visible ) : void {
118- if ( visible ) {
119- this . renderer . removeStyle ( this . host , 'display' ) ;
120- }
121- this . visible = visible ;
150+ this . setDisplay ( true ) ;
122151 this . createPlayer ( visible ) ;
123- this . player . play ( ) ;
152+ this . visible = visible ;
153+ this . player ?. play ( ) ;
124154 }
125155
126156 destroyPlayer ( ) : void {
127- if ( this . player ) {
128- this . player . destroy ( ) ;
129- }
157+ this . player ?. destroy ( ) ;
130158 }
131159
132160 createPlayer ( visible : boolean = this . visible ) : void {
133- if ( this . player ) {
161+ if ( this . player ?. hasStarted ( ) ) {
134162 this . destroyPlayer ( ) ;
135163 }
136164
137165 let animationFactory ;
138166
139167 const duration = this . animate ? this . duration : '0ms' ;
140168
169+ const expand = this . horizontal ? expandHorizontalAnimation : expandAnimation ;
170+ const collapse = this . horizontal ? collapseHorizontalAnimation : collapseAnimation ;
171+
141172 animationFactory = this . animationBuilder . build (
142- useAnimation ( visible ? expandAnimation : collapseAnimation , { params : { time : duration , easing : this . transition } } )
173+ useAnimation ( visible ? expand : collapse , { params : { time : duration , easing : this . transition } } )
143174 ) ;
144175
145176 this . player = animationFactory . create ( this . host ) ;
146- this . player . onStart ( ( ) => { this . collapseChange . emit ( visible ? 'opening' : 'collapsing' ) ; } ) ;
147- this . player . onDone ( ( ) => { this . collapseChange . emit ( visible ? 'open' : 'collapsed' ) ; } ) ;
177+ this . player . onStart ( ( ) => {
178+ this . setMaxSize ( ) ;
179+ this . collapsing = true ;
180+ this . collapseChange . emit ( visible ? 'opening' : 'collapsing' ) ;
181+ } ) ;
182+ this . player . onDone ( ( ) => {
183+ this . collapsing = false ;
184+ this . collapseChange . emit ( visible ? 'open' : 'collapsed' ) ;
185+ } ) ;
148186 }
149187
150- ngAfterViewInit ( ) : void {
151- this . toggle ( ) ;
188+ setMaxSize ( ) {
189+ setTimeout ( ( ) => {
190+ if ( this . horizontal ) {
191+ this . scrollWidth = this . host . scrollWidth ;
192+ this . scrollWidth > 0 && this . renderer . setStyle ( this . host , 'maxWidth' , `${ this . scrollWidth } px` ) ;
193+ // } else {
194+ // this.scrollHeight = this.host.scrollHeight;
195+ // this.scrollHeight > 0 && this.renderer.setStyle(this.host, 'maxHeight', `${this.scrollHeight}px`);
196+ }
197+ } ) ;
198+ }
199+
200+ setDisplay ( display : boolean ) {
201+ display ? this . renderer . removeStyle ( this . host , 'display' ) : this . renderer . setStyle ( this . host , 'display' , 'none' ) ;
152202 }
153203}
0 commit comments