@@ -3,17 +3,18 @@ import { NgClass, NgStyle, NgTemplateOutlet } from '@angular/common';
33import {
44 booleanAttribute ,
55 Component ,
6+ computed ,
67 ElementRef ,
78 forwardRef ,
8- HostBinding ,
99 inject ,
10- Input ,
10+ input ,
1111 OnChanges ,
1212 OnDestroy ,
1313 OnInit ,
1414 Renderer2 ,
15+ signal ,
1516 SimpleChanges ,
16- ViewChild
17+ viewChild
1718} from '@angular/core' ;
1819import { NavigationEnd , Router , RouterModule } from '@angular/router' ;
1920import { Observable , Subscription } from 'rxjs' ;
@@ -65,7 +66,10 @@ import { IconDirective } from '@coreui/icons-angular';
6566 ) ,
6667 transition ( 'open <=> closed' , [ animate ( '.15s ease' ) ] )
6768 ] )
68- ]
69+ ] ,
70+ host : {
71+ '[class]' : 'hostClasses()'
72+ }
6973} )
7074export class SidebarNavGroupComponent implements OnInit , OnDestroy {
7175 readonly #router = inject ( Router ) ;
@@ -82,34 +86,36 @@ export class SidebarNavGroupComponent implements OnInit, OnDestroy {
8286 ) as Observable < NavigationEnd > ;
8387 }
8488
85- @ Input ( ) item : any ;
86- @ Input ( ) dropdownMode : 'path' | 'none' | 'close' = 'path' ;
87- @ Input ( ) show ?: boolean ;
88- @ Input ( { transform : booleanAttribute } ) compact ?: boolean ;
89+ readonly item = input < INavData > ( ) ;
90+ readonly dropdownMode = input < 'path' | 'none' | 'close' > ( 'path' ) ;
91+ readonly show = input < boolean > ( ) ;
92+ readonly compact = input < boolean , unknown > ( undefined , { transform : booleanAttribute } ) ;
8993
90- @HostBinding ( 'class' )
91- get hostClasses ( ) : any {
94+ readonly hostClasses = computed ( ( ) => {
9295 return {
9396 'nav-group' : true ,
94- show : this . open
97+ show : this . open ( )
9598 } ;
96- }
99+ } ) ;
97100
98- @ViewChild ( forwardRef ( ( ) => SidebarNavComponent ) , { read : ElementRef } ) sidebarNav ! : ElementRef ;
101+ readonly sidebarNav = viewChild . required (
102+ forwardRef ( ( ) => SidebarNavComponent ) ,
103+ { read : ElementRef }
104+ ) ;
99105
100106 navigationEndObservable : Observable < NavigationEnd > ;
101107 navSubscription ! : Subscription ;
102108 navGroupSubscription ! : Subscription ;
103109
104- public open ! : boolean ;
105- public navItems : INavData [ ] = [ ] ;
106- public display : any = { display : 'block' } ;
110+ readonly open = signal < boolean | undefined > ( undefined ) ;
111+ readonly navItems = signal < INavData [ ] > ( [ ] ) ;
112+ readonly display = signal < any > ( { display : 'block' } ) ;
107113
108114 ngOnInit ( ) : void {
109- this . navItems = [ ...this . item . children ] ;
115+ this . navItems . set ( [ ...( this . item ( ) ? .children ?? [ ] ) ] ) ;
110116
111117 this . navSubscription = this . navigationEndObservable . subscribe ( ( event : NavigationEnd ) => {
112- if ( this . dropdownMode !== 'none' ) {
118+ if ( this . dropdownMode ( ) !== 'none' ) {
113119 const samePath = this . samePath ( event . url ) ;
114120 this . openGroup ( samePath ) ;
115121 }
@@ -120,8 +126,12 @@ export class SidebarNavGroupComponent implements OnInit, OnDestroy {
120126 }
121127
122128 this . navGroupSubscription = this . #sidebarNavGroupService. sidebarNavGroupState$ . subscribe ( ( next ) => {
123- if ( this . dropdownMode === 'close' && next . sidebarNavGroup && next . sidebarNavGroup !== this ) {
124- if ( next . sidebarNavGroup . item . url . startsWith ( this . item . url ) ) {
129+ if ( this . dropdownMode ( ) === 'close' && next . sidebarNavGroup && next . sidebarNavGroup !== this ) {
130+ const url = next . sidebarNavGroup . item ( ) ?. url ?? [ ] ;
131+ const normUrl = Array . isArray ( url ) ? this . #router. createUrlTree ( url ) . toString ( ) : url ;
132+ const itemUrl = this . item ( ) ?. url ?? [ ] ;
133+ const normItemUrl = Array . isArray ( normUrl ) ? this . #router. createUrlTree ( normUrl ) . toString ( ) : normUrl ;
134+ if ( normUrl . startsWith ( normItemUrl ) ) {
125135 return ;
126136 }
127137 if ( this . samePath ( this . #router. routerState . snapshot . url ) ) {
@@ -135,7 +145,8 @@ export class SidebarNavGroupComponent implements OnInit, OnDestroy {
135145
136146 samePath ( url : string ) : boolean {
137147 // console.log('item:', this.item.name, this.item.url, 'url:', url);
138- const itemArray = this . item . url ?. split ( '/' ) ;
148+ const itemUrl = this . item ( ) ?. url ?? [ ] ;
149+ const itemArray = Array . isArray ( itemUrl ) ? itemUrl : itemUrl . split ( '/' ) ;
139150 const urlArray = url . split ( '/' ) ;
140151 return itemArray ?. every ( ( value : string , index : number ) => {
141152 // console.log(value === urlArray[index], 'value:', value, 'index:', index, urlArray[index], url);
@@ -144,14 +155,14 @@ export class SidebarNavGroupComponent implements OnInit, OnDestroy {
144155 }
145156
146157 openGroup ( open : boolean ) : void {
147- this . open = open ;
158+ this . open . set ( open ) ;
148159 }
149160
150161 toggleGroup ( $event : any ) : void {
151162 $event . preventDefault ( ) ;
152- this . openGroup ( ! this . open ) ;
153- if ( this . open ) {
154- this . #sidebarNavGroupService. toggle ( { open : this . open , sidebarNavGroup : this } ) ;
163+ this . openGroup ( ! this . open ( ) ) ;
164+ if ( this . open ( ) ) {
165+ this . #sidebarNavGroupService. toggle ( { open : this . open ( ) , sidebarNavGroup : this } ) ;
155166 }
156167 }
157168
@@ -160,9 +171,9 @@ export class SidebarNavGroupComponent implements OnInit, OnDestroy {
160171 }
161172
162173 onAnimationStart ( $event : AnimationEvent ) {
163- this . display = { display : 'block' } ;
174+ this . display . set ( { display : 'block' } ) ;
164175 setTimeout ( ( ) => {
165- const host = this . sidebarNav ?. nativeElement ;
176+ const host = this . sidebarNav ( ) ?. nativeElement ;
166177 if ( $event . toState === 'open' && host ) {
167178 this . #renderer. setStyle ( host , 'height' , `${ host [ 'scrollHeight' ] } px` ) ;
168179 }
@@ -171,13 +182,13 @@ export class SidebarNavGroupComponent implements OnInit, OnDestroy {
171182
172183 onAnimationDone ( $event : AnimationEvent ) {
173184 setTimeout ( ( ) => {
174- const host = this . sidebarNav ?. nativeElement ;
185+ const host = this . sidebarNav ( ) ?. nativeElement ;
175186 if ( $event . toState === 'open' && host ) {
176187 this . #renderer. setStyle ( host , 'height' , 'auto' ) ;
177188 }
178189 if ( $event . toState === 'closed' ) {
179190 setTimeout ( ( ) => {
180- this . display = null ;
191+ this . display . set ( null ) ;
181192 } ) ;
182193 }
183194 } ) ;
@@ -197,7 +208,11 @@ export class SidebarNavGroupComponent implements OnInit, OnDestroy {
197208 forwardRef ( ( ) => SidebarNavGroupComponent ) ,
198209 SidebarNavItemClassPipe ,
199210 RouterModule
200- ]
211+ ] ,
212+ host : {
213+ '[class]' : 'hostClasses()' ,
214+ '[attr.role]' : 'role()'
215+ }
201216} )
202217export class SidebarNavComponent implements OnChanges {
203218 readonly sidebar = inject ( SidebarComponent , { optional : true } ) ;
@@ -207,33 +222,31 @@ export class SidebarNavComponent implements OnChanges {
207222 readonly #hostElement = inject ( ElementRef ) ;
208223 readonly #sidebarService = inject ( SidebarService ) ;
209224
210- @Input ( ) navItems ?: INavData [ ] = [ ] ;
211- @Input ( ) dropdownMode : 'path' | 'none' | 'close' = 'path' ;
212- @Input ( { transform : booleanAttribute } ) groupItems ?: boolean ;
213- @Input ( { transform : booleanAttribute } ) compact ?: boolean ;
225+ readonly navItems = input < INavData [ ] | undefined > ( [ ] ) ;
226+ readonly dropdownMode = input < 'path' | 'none' | 'close' > ( 'path' ) ;
227+ readonly groupItems = input < boolean , unknown > ( undefined , { transform : booleanAttribute } ) ;
228+ readonly compact = input < boolean , unknown > ( undefined , { transform : booleanAttribute } ) ;
229+ readonly role = input ( 'navigation' ) ;
214230
215- @ HostBinding ( 'class' )
216- get hostClasses ( ) : any {
231+ readonly hostClasses = computed ( ( ) => {
232+ const groupItems = this . groupItems ( ) ;
217233 return {
218- 'sidebar-nav' : ! this . groupItems ,
219- 'nav-group-items' : this . groupItems ,
220- compact : this . groupItems && this . compact
234+ 'sidebar-nav' : ! groupItems ,
235+ 'nav-group-items' : groupItems ,
236+ compact : groupItems && this . compact ( )
221237 } ;
222- }
238+ } ) ;
223239
224240 // @HostBinding ('class.nav-group-items')
225241 // get sidebarNavGroupItemsClass(): boolean {
226242 // return !!this.groupItems;
227243 // }
228244
229- @HostBinding ( 'attr.role' )
230- @Input ( )
231- role = 'navigation' ;
232-
233- public navItemsArray : INavData [ ] = [ ] ;
245+ readonly navItemsArray = signal < INavData [ ] > ( [ ] ) ;
234246
235247 public ngOnChanges ( changes : SimpleChanges ) : void {
236- this . navItemsArray = Array . isArray ( this . navItems ) ? this . navItems . slice ( ) : [ ] ;
248+ const navItems = this . navItems ( ) ;
249+ this . navItemsArray . set ( Array . isArray ( navItems ) ? navItems . slice ( ) : [ ] ) ;
237250 }
238251
239252 public hideMobile ( ) : void {
0 commit comments