11import {
22AfterContentInit ,
3+ AfterViewInit ,
34ChangeDetectorRef ,
45Component ,
56ContentChild ,
@@ -20,20 +21,41 @@ import {
2021import { DOCUMENT } from '@angular/common' ;
2122import { BooleanInput , coerceBooleanProperty } from '@angular/cdk/coercion' ;
2223import { Subscription } from 'rxjs' ;
24+
2325import { createPopper , Instance , Options , Placement } from '@popperjs/core' ;
2426
2527import { DropdownService } from '../dropdown.service' ;
2628import { DropdownMenuDirective } from '../dropdown-menu/dropdown-menu.directive' ;
2729
2830@Directive ( {
2931selector :'[cDropdownToggle]' ,
30- exportAs :'cDropdownToggle' ,
32+ exportAs :'cDropdownToggle'
3133} )
32- export class DropdownToggleDirective {
34+ export class DropdownToggleDirective implements AfterViewInit {
3335
3436static ngAcceptInputType_split :BooleanInput ;
3537static ngAcceptInputType_popper :BooleanInput ;
3638
39+ constructor (
40+ public elementRef :ElementRef ,
41+ private dropdownService :DropdownService ,
42+ @Optional ( ) public dropdown ?:DropdownComponent
43+ ) { }
44+
45+ /**
46+ * Toggle the disabled state for the toggler.
47+ *@type DropdownComponent | undefined
48+ *@default undefined
49+ */
50+ @Input ( ) dropdownComponent ?:DropdownComponent ;
51+
52+ /**
53+ * Disables the toggler.
54+ *@type boolean
55+ *@default false
56+ */
57+ @Input ( ) disabled ?:boolean = false ;
58+
3759/**
3860 * Enables pseudo element caret on toggler.
3961 *@type boolean
@@ -53,24 +75,26 @@ export class DropdownToggleDirective {
5375}
5476private _split = false ;
5577
56- constructor (
57- public elementRef :ElementRef ,
58- private dropdownService :DropdownService ,
59- @Optional ( ) public dropdown ?:DropdownComponent
60- ) { }
61-
6278 @HostBinding ( 'class' )
6379get hostClasses ( ) :any {
6480return {
6581'dropdown-toggle' :this . caret ,
6682'dropdown-toggle-split' :this . split ,
83+ disabled :this . disabled
6784} ;
6885}
6986
7087 @HostListener ( 'click' , [ '$event' ] )
7188public onClick ( $event :MouseEvent ) :void {
7289$event . preventDefault ( ) ;
73- this . dropdownService . toggle ( { visible :'toggle' , dropdown :this . dropdown } ) ;
90+ ! this . disabled && this . dropdownService . toggle ( { visible :'toggle' , dropdown :this . dropdown } ) ;
91+ }
92+
93+ ngAfterViewInit ( ) :void {
94+ if ( this . dropdownComponent ) {
95+ this . dropdown = this . dropdownComponent ;
96+ this . dropdownService = this . dropdownComponent ?. dropdownService ;
97+ }
7498}
7599}
76100
@@ -79,7 +103,7 @@ export class DropdownToggleDirective {
79103template :'<ng-content></ng-content>' ,
80104styleUrls :[ './dropdown.component.scss' ] ,
81105exportAs :'cDropdown' ,
82- providers :[ DropdownService ] ,
106+ providers :[ DropdownService ]
83107} )
84108export class DropdownComponent implements AfterContentInit , OnDestroy , OnInit {
85109
@@ -164,7 +188,6 @@ export class DropdownComponent implements AfterContentInit, OnDestroy, OnInit {
164188this . _popperOptions = { ...this . _popperOptions , placement :placement } ;
165189return this . _popperOptions ;
166190}
167-
168191private _popperOptions :Partial < Options > = {
169192placement :this . placement ,
170193modifiers :[ ] ,
@@ -196,7 +219,7 @@ export class DropdownComponent implements AfterContentInit, OnDestroy, OnInit {
196219
197220 @Output ( ) visibleChange :EventEmitter < boolean > = new EventEmitter < boolean > ( ) ;
198221
199- dropdownContext = { $implicit :this . visible } ;
222+ dropdownContext = { $implicit :this . visible } ;
200223 @ContentChild ( DropdownToggleDirective ) _toggler ! :DropdownToggleDirective ;
201224 @ContentChild ( DropdownMenuDirective ) _menu ! :DropdownMenuDirective ;
202225
@@ -212,7 +235,7 @@ export class DropdownComponent implements AfterContentInit, OnDestroy, OnInit {
212235private renderer :Renderer2 ,
213236private ngZone :NgZone ,
214237private changeDetectorRef :ChangeDetectorRef ,
215- private dropdownService :DropdownService
238+ public dropdownService :DropdownService
216239) { }
217240
218241 @HostBinding ( 'class' )
@@ -225,14 +248,14 @@ export class DropdownComponent implements AfterContentInit, OnDestroy, OnInit {
225248'btn-group' :this . variant === 'btn-group' ,
226249'nav-item' :this . variant === 'nav-item' ,
227250'input-group' :this . variant === 'input-group' ,
228- show :this . visible ,
251+ show :this . visible
229252} ;
230253}
231254
232255// todo: find better solution
233256 @HostBinding ( 'style' )
234257get hostStyle ( ) :any {
235- return this . variant === 'input-group' ?{ display :'contents' } :{ } ;
258+ return this . variant === 'input-group' ?{ display :'contents' } :{ } ;
236259}
237260
238261private clickedTarget ! :HTMLElement ;
@@ -287,7 +310,7 @@ export class DropdownComponent implements AfterContentInit, OnDestroy, OnInit {
287310}
288311
289312setVisibleState ( value :boolean ) :void {
290- this . dropdownService . toggle ( { visible :value , dropdown :this } ) ;
313+ this . dropdownService . toggle ( { visible :value , dropdown :this } ) ;
291314}
292315
293316// todo: turn off popper in navbar-nav
@@ -301,7 +324,7 @@ export class DropdownComponent implements AfterContentInit, OnDestroy, OnInit {
301324this . popperInstance = createPopper (
302325this . _toggler . elementRef . nativeElement ,
303326this . _menu . elementRef . nativeElement ,
304- { ...this . popperOptions }
327+ { ...this . popperOptions }
305328) ;
306329}
307330this . ngZone . run ( ( ) => {
@@ -331,13 +354,13 @@ export class DropdownComponent implements AfterContentInit, OnDestroy, OnInit {
331354return ;
332355}
333356if ( this . clickedTarget === target && this . autoClose === 'inside' ) {
334- this . setVisibleState ( false ) ;
335- return ;
336- }
357+ this . setVisibleState ( false ) ;
358+ return ;
359+ }
337360if ( this . clickedTarget !== target && this . autoClose === 'outside' ) {
338- this . setVisibleState ( false ) ;
339- return ;
340- }
361+ this . setVisibleState ( false ) ;
362+ return ;
363+ }
341364} )
342365) ;
343366this . listeners . push (