• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

IgniteUI / igniteui-angular / 16369285158

18 Jul 2025 11:20AM UTC coverage: 91.419% (+0.009%) from 91.41%
16369285158

Pull #16059

github

web-flow
Merge pull request #16060 from IgniteUI/sstoychev/fix-codeql

fix(ci): fixing codeql execution rules
Pull Request #16059: Mass Merging 20.0.x to master

13433 of 15774 branches covered (85.16%)

16 of 18 new or added lines in 5 files covered. (88.89%)

37 existing lines in 5 files now uncovered.

27147 of 29695 relevant lines covered (91.42%)

36682.48 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

83.82
/projects/igniteui-angular/src/lib/combo/combo-dropdown.component.ts
1
import {
2
    ChangeDetectorRef, Component, ElementRef, Inject, QueryList, OnDestroy, AfterViewInit, ContentChildren, Input, booleanAttribute, DOCUMENT
3
} from '@angular/core';
4
import { IgxComboBase, IGX_COMBO_COMPONENT } from './combo.common';
5
import { IDropDownBase, IGX_DROPDOWN_BASE } from '../drop-down/drop-down.common';
6
import { IgxDropDownComponent } from '../drop-down/drop-down.component';
7
import { DropDownActionKey } from '../drop-down/drop-down.common';
8
import { IgxComboAddItemComponent } from './combo-add-item.component';
9
import { IgxComboAPIService } from './combo.api';
10
import { IgxDropDownItemBaseDirective } from '../drop-down/drop-down-item.base';
11
import { IgxSelectionAPIService } from '../core/selection';
12
import { IgxComboItemComponent } from './combo-item.component';
13
import { IgxToggleDirective } from '../directives/toggle/toggle.directive';
14

15
/** @hidden */
16
@Component({
17
    selector: 'igx-combo-drop-down',
18
    templateUrl: '../drop-down/drop-down.component.html',
19
    providers: [{ provide: IGX_DROPDOWN_BASE, useExisting: IgxComboDropDownComponent }],
20
    imports: [IgxToggleDirective]
21
})
22
export class IgxComboDropDownComponent extends IgxDropDownComponent implements IDropDownBase, OnDestroy, AfterViewInit {
3✔
23
    /** @hidden @internal */
24
    @Input({ transform: booleanAttribute })
25
    public singleMode = false;
386✔
26

27
    /**
28
     * @hidden
29
     * @internal
30
     */
31
    @ContentChildren(IgxComboItemComponent, { descendants: true })
32
    public override children: QueryList<IgxDropDownItemBaseDirective> = null;
386✔
33

34
    /** @hidden @internal */
35
    public override get scrollContainer(): HTMLElement {
36
        // TODO: Update, use public API if possible:
37
        return this.virtDir.dc.location.nativeElement;
1✔
38
    }
39

40
    protected get isScrolledToLast(): boolean {
41
        const scrollTop = this.virtDir.scrollPosition;
×
42
        const scrollHeight = this.virtDir.getScroll().scrollHeight;
×
43
        return Math.floor(scrollTop + this.virtDir.igxForContainerSize) === scrollHeight;
×
44
    }
45

46
    protected get lastVisibleIndex(): number {
47
        return this.combo.totalItemCount ?
×
48
            Math.floor(this.combo.itemsMaxHeight / this.combo.itemHeight) :
49
            this.items.length - 1;
50
    }
51

52
    protected get sortedChildren(): IgxDropDownItemBaseDirective[] {
53
        if (this.children !== undefined) {
125✔
54
            return this.children.toArray()
125✔
55
                .sort((a: IgxDropDownItemBaseDirective, b: IgxDropDownItemBaseDirective) => a.index - b.index);
1,030✔
56
        }
57
        return null;
×
58
    }
59

60
    /**
61
     * Get all non-header items
62
     *
63
     * ```typescript
64
     * let myDropDownItems = this.dropdown.items;
65
     * ```
66
     */
67
    public override get items(): IgxComboItemComponent[] {
68
        const items: IgxComboItemComponent[] = [];
125✔
69
        if (this.children !== undefined) {
125✔
70
            const sortedChildren = this.sortedChildren as IgxComboItemComponent[];
125✔
71
            for (const child of sortedChildren) {
125✔
72
                if (!child.isHeader) {
1,148✔
73
                    items.push(child);
942✔
74
                }
75
            }
76
        }
77

78
        return items;
125✔
79
    }
80

81
    constructor(
82
        elementRef: ElementRef,
83
        cdr: ChangeDetectorRef,
84
        @Inject(DOCUMENT) document: any,
85
        selection: IgxSelectionAPIService,
86
        @Inject(IGX_COMBO_COMPONENT) public combo: IgxComboBase,
386✔
87
        protected comboAPI: IgxComboAPIService) {
386✔
88
        super(elementRef, cdr, document, selection);
386✔
89
    }
90

91
    /**
92
     * @hidden @internal
93
     */
94
    public onFocus() {
95
        this.focusedItem = this._focusedItem || this.items[0];
28✔
96
        this.combo.setActiveDescendant();
28✔
97
    }
98

99
    /**
100
     * @hidden @internal
101
     */
102
    public onBlur(_evt?) {
103
        this.focusedItem = null;
56✔
104
        this.combo.setActiveDescendant();
56✔
105
    }
106

107
    /**
108
     * @hidden @internal
109
     */
110
    public override onToggleOpened() {
111
        this.opened.emit();
71✔
112
    }
113

114
    /**
115
     * @hidden
116
     */
117
    public override navigateFirst() {
118
        this.navigateItem(this.virtDir.igxForOf.findIndex(e => !e?.isHeader));
54✔
119
        this.combo.setActiveDescendant();
29✔
120
    }
121

122
    /**
123
     * @hidden
124
     */
125
    public override navigatePrev() {
126
        if (this._focusedItem && this._focusedItem.index === 0 && this.virtDir.state.startIndex === 0) {
9✔
127
            this.combo.focusSearchInput(false);
2✔
128
            this.focusedItem = null;
2✔
129
        } else {
130
            super.navigatePrev();
7✔
131
        }
132
        this.combo.setActiveDescendant();
9✔
133
    }
134

135

136
    /**
137
     * @hidden
138
     */
139
    public override navigateNext() {
140
        const lastIndex = this.combo.totalItemCount ? this.combo.totalItemCount - 1 : this.virtDir.igxForOf.length - 1;
23!
141
        if (this._focusedItem && this._focusedItem.index === lastIndex) {
23✔
142
            this.focusAddItemButton();
1✔
143
        } else {
144
            super.navigateNext();
22✔
145
        }
146
        this.combo.setActiveDescendant();
23✔
147
    }
148

149
    /**
150
     * @hidden @internal
151
     */
152
    public override selectItem(item: IgxDropDownItemBaseDirective) {
153
        if (item === null || item === undefined) {
5!
154
            return;
×
155
        }
156
        this.comboAPI.set_selected_item(item.itemID);
5✔
157
        this._focusedItem = item;
5✔
158
        this.combo.setActiveDescendant();
5✔
159
    }
160

161
    /**
162
     * @hidden @internal
163
     */
164
    public override updateScrollPosition() {
165
        this.virtDir.getScroll().scrollTop = this._scrollPosition;
167✔
166
    }
167

168
    /**
169
     * @hidden @internal
170
     */
171
    public override onItemActionKey(key: DropDownActionKey) {
172
        switch (key) {
8!
173
            case DropDownActionKey.ENTER:
174
                this.handleEnter();
1✔
175
                break;
1✔
176
            case DropDownActionKey.SPACE:
177
                this.handleSpace();
7✔
178
                break;
7✔
179
            case DropDownActionKey.ESCAPE:
NEW
180
                this.close();
×
181
        }
182
    }
183

184
    public override ngAfterViewInit() {
185
        this.virtDir.getScroll().addEventListener('scroll', this.scrollHandler);
386✔
186
    }
187

188
    /**
189
     * @hidden @internal
190
     */
191
    public override ngOnDestroy(): void {
192
        this.virtDir.getScroll().removeEventListener('scroll', this.scrollHandler);
386✔
193
        super.ngOnDestroy();
386✔
194
    }
195

196
    protected override scrollToHiddenItem(_newItem: any): void { }
197

198
    protected scrollHandler = () => {
386✔
199
        this.comboAPI.disableTransitions = true;
20✔
200
    };
201

202
    private handleEnter() {
203
        if (this.isAddItemFocused()) {
1✔
204
            this.combo.addItemToCollection();
1✔
205
            return;
1✔
206
        }
UNCOV
207
        if (this.singleMode && this.focusedItem) {
×
208
            this.combo.select(this.focusedItem.itemID);
×
209
        }
210

UNCOV
211
        this.close();
×
212
    }
213

214
    private handleSpace() {
215
        if (this.isAddItemFocused()) {
7✔
216
            return;
2✔
217
        } else {
218
            this.selectItem(this.focusedItem);
5✔
219
        }
220
    }
221

222
    private isAddItemFocused(): boolean {
223
        return this.focusedItem instanceof IgxComboAddItemComponent;
8✔
224
    }
225

226
    private focusAddItemButton() {
227
        if (this.combo.isAddButtonVisible()) {
1!
UNCOV
228
            this.focusedItem = this.items[this.items.length - 1];
×
229
        }
230
    }
231
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc