11/** Angular Imports */
2- import { Component , TemplateRef , ElementRef , ViewChild , AfterViewInit , inject } from '@angular/core' ;
2+ import { Component , TemplateRef , ElementRef , ViewChild , AfterViewInit , OnDestroy , inject } from '@angular/core' ;
33import { ActivatedRoute , Router , NavigationEnd , Data , RouterLink } from '@angular/router' ;
44
55/** rxjs Imports */
6- import { filter } from 'rxjs/operators' ;
6+ import { filter , takeUntil } from 'rxjs/operators' ;
7+ import { merge , Subject } from 'rxjs' ;
78
89/** Custom Model */
910import { Breadcrumb } from './breadcrumb.model' ;
@@ -54,12 +55,13 @@ const routeAddBreadcrumbLink = 'addBreadcrumbLink';
5455 ...STANDALONE_SHARED_IMPORTS
5556 ]
5657} )
57- export class BreadcrumbComponent implements AfterViewInit {
58+ export class BreadcrumbComponent implements AfterViewInit , OnDestroy {
5859 private activatedRoute = inject ( ActivatedRoute ) ;
5960 private router = inject ( Router ) ;
6061 private configurationWizardService = inject ( ConfigurationWizardService ) ;
6162 private popoverService = inject ( PopoverService ) ;
6263 private translateService = inject ( TranslateService ) ;
64+ private destroy$ = new Subject < void > ( ) ;
6365
6466 /** Array of breadcrumbs. */
6567 breadcrumbs : Breadcrumb [ ] ;
@@ -85,142 +87,130 @@ export class BreadcrumbComponent implements AfterViewInit {
8587 generateBreadcrumbs ( ) {
8688 const onNavigationEnd = this . router . events . pipe ( filter ( ( event ) => event instanceof NavigationEnd ) ) ;
8789
88- onNavigationEnd . subscribe ( ( ) => {
89- this . breadcrumbs = [ ] ;
90- let currentRoute = this . activatedRoute . root ;
91- let currentUrl = '' ;
90+ // Merge navigation events with language change events to regenerate breadcrumbs when language changes
91+ merge ( onNavigationEnd , this . translateService . onLangChange )
92+ . pipe ( takeUntil ( this . destroy$ ) )
93+ . subscribe ( ( ) => {
94+ this . breadcrumbs = [ ] ;
95+ let currentRoute = this . activatedRoute . root ;
96+ let currentUrl = '' ;
9297
93- while ( currentRoute . children . length > 0 ) {
94- const childrenRoutes = currentRoute . children ;
95- let breadcrumbLabel : any ;
96- let url : any ;
98+ while ( currentRoute . children . length > 0 ) {
99+ const childrenRoutes = currentRoute . children ;
100+ let breadcrumbLabel : any ;
101+ let url : any ;
97102
98- childrenRoutes . forEach ( ( route ) => {
99- currentRoute = route ;
100- breadcrumbLabel = false ;
103+ childrenRoutes . forEach ( ( route ) => {
104+ currentRoute = route ;
105+ breadcrumbLabel = false ;
101106
102- if ( route . outlet !== 'primary' ) {
103- return ;
104- }
107+ if ( route . outlet !== 'primary' ) {
108+ return ;
109+ }
105110
106- const routeURL = route . snapshot . url . map ( ( segment ) => segment . path ) . join ( '/' ) ;
107- currentUrl += `/${ routeURL } ` ;
111+ const routeURL = route . snapshot . url . map ( ( segment ) => segment . path ) . join ( '/' ) ;
112+ currentUrl += `/${ routeURL } ` ;
108113
109- if ( currentUrl === '/' ) {
110- breadcrumbLabel = 'Home' ;
111- }
114+ if ( currentUrl === '/' ) {
115+ breadcrumbLabel = 'Home' ;
116+ }
112117
113- const hasData = route . routeConfig && route . routeConfig . data ;
118+ const hasData = route . routeConfig && route . routeConfig . data ;
114119
115- if ( hasData ) {
116- if (
117- route . snapshot . data . hasOwnProperty ( routeResolveBreadcrumb ) &&
118- route . snapshot . data [ routeResolveBreadcrumb ]
119- ) {
120- breadcrumbLabel = route . snapshot . data ;
121- route . snapshot . data [ routeResolveBreadcrumb ] . forEach ( ( property : any ) => {
122- breadcrumbLabel = breadcrumbLabel [ property ] ;
123- } ) ;
124- } else if (
125- route . snapshot . data . hasOwnProperty ( routeParamBreadcrumb ) &&
126- route . snapshot . paramMap . get ( route . snapshot . data [ routeParamBreadcrumb ] )
127- ) {
128- breadcrumbLabel = route . snapshot . paramMap . get ( route . snapshot . data [ routeParamBreadcrumb ] ) ;
129- const routeData : Data = route . snapshot . data ;
130- if ( routeData . breadcrumb === 'Clients' ) {
131- breadcrumbLabel = this . printableValue ( routeData . clientViewData . displayName ) ;
132- currentUrl += `/general` ;
133- } else if ( routeData . breadcrumb === 'Groups' ) {
134- breadcrumbLabel = routeData . groupViewData . name ;
135- } else if ( routeData . breadcrumb === 'Centers' ) {
136- breadcrumbLabel = routeData . centerViewData . name ;
137- } else if ( routeData . breadcrumb === 'Loans' ) {
138- breadcrumbLabel =
139- this . printableValue ( routeData . loanDetailsData . loanProductName ) +
140- ' (' +
141- routeData . loanDetailsData . accountNo +
142- ')' ;
143- } else if ( routeData . breadcrumb === 'Savings' ) {
144- const savingsProductName = routeData . savingsAccountData ?. savingsProductName ?? '' ;
145- const accountNo = routeData . savingsAccountData ?. accountNo ?? '' ;
146- breadcrumbLabel = this . printableValue ( savingsProductName ) + ( accountNo ? ' (' + accountNo + ')' : '' ) ;
147- } else if ( routeData . breadcrumb === 'Fixed Deposits' ) {
148- breadcrumbLabel =
149- this . printableValue ( routeData . fixedDepositsAccountData . depositProductName ) +
150- ' (' +
151- routeData . fixedDepositsAccountData . accountNo +
152- ')' ;
153- } else if ( routeData . breadcrumb === 'Loan Products' ) {
154- breadcrumbLabel = this . printableValue ( routeData . loanProduct . name ) ;
155- } else if ( routeData . breadcrumb === 'Charges' ) {
156- breadcrumbLabel = routeData . loansAccountCharge . name ;
157- } else if ( routeData . breadcrumb === 'Saving Products' ) {
158- breadcrumbLabel = routeData . savingProduct . name ;
159- } else if ( routeData . breadcrumb === 'Share Products' ) {
160- breadcrumbLabel = routeData . shareProduct . name ;
161- } else if ( routeData . breadcrumb === 'Fixed Deposit Products' ) {
162- breadcrumbLabel = routeData . fixedDepositProduct . name ;
163- } else if ( routeData . breadcrumb === 'Recurring Deposit Products' ) {
164- breadcrumbLabel = routeData . recurringDepositProduct . name ;
165- } else if ( routeData . breadcrumb === 'Floating Rates' ) {
166- breadcrumbLabel = routeData . floatingRate . name ;
167- } else if ( routeData . breadcrumb === 'Tax Components' ) {
168- breadcrumbLabel = routeData . taxComponent . name ;
169- } else if ( routeData . breadcrumb === 'Tax Groups' ) {
170- breadcrumbLabel = routeData . taxGroup . name ;
171- }
172-
173- // Check if the breadcrumbLabel is an action name that should be translated using labels.menus
174- // This handles action names from route parameters for Savings, Loans, Shares, Fixed Deposits, and Recurring Deposits accounts
120+ if ( hasData ) {
175121 if (
176- breadcrumbLabel &&
177- ( routeData . breadcrumb === 'Savings Account Actions' ||
178- routeData . breadcrumb === 'Loan Account Actions' ||
179- routeData . breadcrumb === 'Shares Account Actions' ||
180- routeData . breadcrumb === 'Actions' ||
181- routeData . breadcrumb === 'action' ||
182- routeData . title === 'Fixed Deposits Account Actions' ||
183- routeData . title === 'Recurring Deposits Account Actions' )
122+ route . snapshot . data . hasOwnProperty ( routeResolveBreadcrumb ) &&
123+ route . snapshot . data [ routeResolveBreadcrumb ]
124+ ) {
125+ breadcrumbLabel = route . snapshot . data ;
126+ route . snapshot . data [ routeResolveBreadcrumb ] . forEach ( ( property : any ) => {
127+ breadcrumbLabel = breadcrumbLabel [ property ] ;
128+ } ) ;
129+ } else if (
130+ route . snapshot . data . hasOwnProperty ( routeParamBreadcrumb ) &&
131+ route . snapshot . paramMap . get ( route . snapshot . data [ routeParamBreadcrumb ] )
184132 ) {
185- const menuKey = 'labels.menus.' + breadcrumbLabel ;
186- const menuTranslation = this . translateService . instant ( menuKey ) ;
187- if ( menuTranslation !== menuKey ) {
188- breadcrumbLabel = menuTranslation ;
133+ breadcrumbLabel = route . snapshot . paramMap . get ( route . snapshot . data [ routeParamBreadcrumb ] ) ;
134+ const routeData : Data = route . snapshot . data ;
135+ if ( routeData . breadcrumb === 'Clients' ) {
136+ breadcrumbLabel = this . printableValue ( routeData . clientViewData . displayName ) ;
137+ currentUrl += `/general` ;
138+ } else if ( routeData . breadcrumb === 'Groups' ) {
139+ breadcrumbLabel = routeData . groupViewData . name ;
140+ } else if ( routeData . breadcrumb === 'Centers' ) {
141+ breadcrumbLabel = routeData . centerViewData . name ;
142+ } else if ( routeData . breadcrumb === 'Loans' ) {
143+ breadcrumbLabel =
144+ this . printableValue ( routeData . loanDetailsData . loanProductName ) +
145+ ' (' +
146+ routeData . loanDetailsData . accountNo +
147+ ')' ;
148+ } else if ( routeData . breadcrumb === 'Savings' ) {
149+ const savingsProductName = routeData . savingsAccountData ?. savingsProductName ?? '' ;
150+ const accountNo = routeData . savingsAccountData ?. accountNo ?? '' ;
151+ breadcrumbLabel = this . printableValue ( savingsProductName ) + ( accountNo ? ' (' + accountNo + ')' : '' ) ;
152+ } else if ( routeData . breadcrumb === 'Fixed Deposits' ) {
153+ breadcrumbLabel =
154+ this . printableValue ( routeData . fixedDepositsAccountData . depositProductName ) +
155+ ' (' +
156+ routeData . fixedDepositsAccountData . accountNo +
157+ ')' ;
158+ } else if ( routeData . breadcrumb === 'Loan Products' ) {
159+ breadcrumbLabel = this . printableValue ( routeData . loanProduct . name ) ;
160+ } else if ( routeData . breadcrumb === 'Charges' ) {
161+ breadcrumbLabel = routeData . loansAccountCharge . name ;
162+ } else if ( routeData . breadcrumb === 'Saving Products' ) {
163+ breadcrumbLabel = routeData . savingProduct . name ;
164+ } else if ( routeData . breadcrumb === 'Share Products' ) {
165+ breadcrumbLabel = routeData . shareProduct . name ;
166+ } else if ( routeData . breadcrumb === 'Fixed Deposit Products' ) {
167+ breadcrumbLabel = routeData . fixedDepositProduct . name ;
168+ } else if ( routeData . breadcrumb === 'Recurring Deposit Products' ) {
169+ breadcrumbLabel = routeData . recurringDepositProduct . name ;
170+ } else if ( routeData . breadcrumb === 'Floating Rates' ) {
171+ breadcrumbLabel = routeData . floatingRate . name ;
172+ } else if ( routeData . breadcrumb === 'Tax Components' ) {
173+ breadcrumbLabel = routeData . taxComponent . name ;
174+ } else if ( routeData . breadcrumb === 'Tax Groups' ) {
175+ breadcrumbLabel = routeData . taxGroup . name ;
189176 }
177+
178+ // For action names, keep the original name and let getTranslate() handle translation dynamically
179+ // This ensures breadcrumbs update when language changes without requiring navigation
180+ // The getTranslate() method will check both labels.text.* and labels.menus.* for translations
181+ } else if ( route . snapshot . data . hasOwnProperty ( routeDataBreadcrumb ) ) {
182+ breadcrumbLabel = route . snapshot . data [ routeDataBreadcrumb ] ;
190183 }
191- } else if ( route . snapshot . data . hasOwnProperty ( routeDataBreadcrumb ) ) {
192- breadcrumbLabel = route . snapshot . data [ routeDataBreadcrumb ] ;
193- }
194184
195- if ( route . snapshot . data . hasOwnProperty ( routeAddBreadcrumbLink ) ) {
196- url = route . snapshot . data [ routeAddBreadcrumbLink ] ;
197- } else {
198- url = currentUrl ;
185+ if ( route . snapshot . data . hasOwnProperty ( routeAddBreadcrumbLink ) ) {
186+ url = route . snapshot . data [ routeAddBreadcrumbLink ] ;
187+ } else {
188+ url = currentUrl ;
189+ }
199190 }
200- }
201- if ( url !== undefined ) {
202- if ( url . length > 8 && url . search ( `/clients/` ) > 0 ) {
203- const replaceGeneral = `/general/` ;
204- let currentUrlTemp = url . replace ( replaceGeneral , `/` ) ;
205- currentUrlTemp = currentUrlTemp . replace ( `//` , `/` ) ;
206- currentUrlTemp + = `/general` ;
207- const replaceDoubleSlash = `/general/general` ;
208- currentUrlTemp = currentUrlTemp . replace ( replaceDoubleSlash , `/general` ) ;
209- url = currentUrlTemp ;
191+ if ( url !== undefined ) {
192+ if ( url . length > 8 && url . search ( `/clients/` ) > 0 ) {
193+ const replaceGeneral = `/general/` ;
194+ let currentUrlTemp = url . replace ( replaceGeneral , `/` ) ;
195+ currentUrlTemp = currentUrlTemp . replace ( `//` , `/` ) ;
196+ currentUrlTemp += `/general` ;
197+ const replaceDoubleSlash = `/general /general` ;
198+ currentUrlTemp = currentUrlTemp . replace ( replaceDoubleSlash , `/general` ) ;
199+ url = currentUrlTemp ;
200+ }
210201 }
211- }
212202
213- const breadcrumb : Breadcrumb = {
214- label : breadcrumbLabel ,
215- url : url
216- } ;
203+ const breadcrumb : Breadcrumb = {
204+ label : breadcrumbLabel ,
205+ url : url
206+ } ;
217207
218- if ( breadcrumbLabel ) {
219- this . breadcrumbs . push ( breadcrumb ) ;
220- }
221- } ) ;
222- }
223- } ) ;
208+ if ( breadcrumbLabel ) {
209+ this . breadcrumbs . push ( breadcrumb ) ;
210+ }
211+ } ) ;
212+ }
213+ } ) ;
224214 }
225215
226216 printableValue ( value : string ) : string {
@@ -280,9 +270,29 @@ export class BreadcrumbComponent implements AfterViewInit {
280270 }
281271
282272 getTranslate ( text : string ) : any {
283- const key : string = 'labels.text.' + text ;
284- const translation = this . translateService . instant ( key ) ;
285- const result = translation !== key ? translation : text ;
286- return result ;
273+ // First try labels.text.* (for static breadcrumb labels)
274+ let key : string = 'labels.text.' + text ;
275+ let translation = this . translateService . instant ( key ) ;
276+ if ( translation !== key ) {
277+ return translation ;
278+ }
279+
280+ // Then try labels.menus.* (for action names like "View Guarantors")
281+ key = 'labels.menus.' + text ;
282+ translation = this . translateService . instant ( key ) ;
283+ if ( translation !== key ) {
284+ return translation ;
285+ }
286+
287+ // If no translation found, return the original text
288+ return text ;
289+ }
290+
291+ /**
292+ * Clean up subscriptions on component destroy.
293+ */
294+ ngOnDestroy ( ) : void {
295+ this . destroy$ . next ( ) ;
296+ this . destroy$ . complete ( ) ;
287297 }
288298}
0 commit comments