Skip to content

Commit ea8f333

Browse files
committed
fix(tabs): NG0950 required input is accessed before a value is set
1 parent fe32f4f commit ea8f333

File tree

2 files changed

+27
-11
lines changed

2 files changed

+27
-11
lines changed

projects/coreui-angular/src/lib/tabs-2/tab/tab.directive.ts

+15-4
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,12 @@ import {
77
effect,
88
ElementRef,
99
inject,
10+
Injector,
1011
Input,
1112
input,
1213
InputSignal,
14+
OnInit,
15+
runInInjectionContext,
1316
signal,
1417
untracked
1518
} from '@angular/core';
@@ -32,7 +35,8 @@ import { TabsService } from '../tabs.service';
3235
'[tabindex]': 'isActive() ? 0 : -1'
3336
}
3437
})
35-
export class TabDirective implements FocusableOption {
38+
export class TabDirective implements FocusableOption, OnInit {
39+
readonly #injector = inject(Injector);
3640
readonly #destroyRef = inject(DestroyRef);
3741
readonly #elementRef = inject(ElementRef);
3842
readonly #tabsService = inject(TabsService);
@@ -77,9 +81,7 @@ export class TabDirective implements FocusableOption {
7781
alias: 'aria-controls'
7882
});
7983

80-
readonly isActive = computed<boolean>(
81-
() => !this.#disabled() && this.#tabsService.activeItemKey() === this.itemKey()
82-
);
84+
readonly isActive = signal(false);
8385

8486
readonly hostClasses = computed(() => ({
8587
'nav-link': true,
@@ -114,4 +116,13 @@ export class TabDirective implements FocusableOption {
114116
focus(origin?: FocusOrigin): void {
115117
this.#elementRef.nativeElement.focus();
116118
}
119+
120+
ngOnInit(): void {
121+
runInInjectionContext(this.#injector, () => {
122+
effect(() => {
123+
const isActive = !this.#disabled() && this.#tabsService.activeItemKey() === this.itemKey();
124+
this.isActive.set(isActive);
125+
});
126+
});
127+
}
117128
}

projects/coreui-angular/src/lib/tabs-2/tabs-list/tabs-list.component.ts

+12-7
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,11 @@ export class TabsListComponent {
6060
#focusKeyManager!: FocusKeyManager<TabDirective>;
6161

6262
readonly tabsEffect = effect(() => {
63-
if (this.tabs().length === 0) {
63+
const tabs = this.tabs();
64+
if (tabs.length === 0) {
6465
return;
6566
}
66-
this.#focusKeyManager = new FocusKeyManager(this.tabs())
67+
this.#focusKeyManager = new FocusKeyManager(tabs)
6768
.skipPredicate((tab) => tab.disabled === true)
6869
.withHorizontalOrientation('ltr')
6970
.withHomeAndEnd()
@@ -79,11 +80,15 @@ export class TabsListComponent {
7980
)
8081
.subscribe();
8182

82-
const activeItem = this.tabs().find((tab) => untracked(tab.isActive)) ?? this.tabs().find((tab) => !tab.disabled);
83-
const activeItemIndex = this.tabs().findIndex((tab) => tab === activeItem);
84-
this.#focusKeyManager?.updateActiveItem(activeItemIndex < 0 ? 0 : activeItemIndex);
85-
this.tabsService.activeItemKey.set(this.#focusKeyManager.activeItem?.itemKey());
86-
this.tabsService.activeItem.set(this.#focusKeyManager.activeItem);
83+
untracked(() => {
84+
setTimeout(() => {
85+
const activeItem = tabs.find((tab) => tab.isActive()) ?? tabs.find((tab) => !tab.disabled);
86+
const activeItemIndex = tabs.findIndex((tab) => tab === activeItem);
87+
this.#focusKeyManager?.updateActiveItem(activeItemIndex < 0 ? 0 : activeItemIndex);
88+
this.tabsService.activeItemKey.set(this.#focusKeyManager.activeItem?.itemKey());
89+
this.tabsService.activeItem.set(this.#focusKeyManager.activeItem);
90+
});
91+
});
8792
});
8893

8994
tabsServiceEffect = effect(() => {

0 commit comments

Comments
 (0)