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

IgniteUI / igniteui-angular / 13331632524

14 Feb 2025 02:51PM CUT coverage: 22.015% (-69.6%) from 91.622%
13331632524

Pull #15372

github

web-flow
Merge d52d57714 into bcb78ae0a
Pull Request #15372: chore(*): test ci passing

1990 of 15592 branches covered (12.76%)

431 of 964 new or added lines in 18 files covered. (44.71%)

19956 existing lines in 307 files now uncovered.

6452 of 29307 relevant lines covered (22.02%)

249.17 hits per line

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

14.71
/projects/igniteui-angular/src/lib/combo/combo-dropdown.component.ts
1
import {
2
    ChangeDetectorRef, Component, ElementRef, Inject, QueryList, OnDestroy, AfterViewInit, ContentChildren, Input, booleanAttribute
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 { DOCUMENT, NgIf } from '@angular/common';
14
import { IgxToggleDirective } from '../directives/toggle/toggle.directive';
15

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

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

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

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

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

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

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

UNCOV
79
        return items;
×
80
    }
81

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

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

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

108
    /**
109
     * @hidden @internal
110
     */
111
    public override onToggleOpened() {
UNCOV
112
        this.opened.emit();
×
113
    }
114

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

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

136

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

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

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

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

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

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

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

199
    protected scrollHandler = () => {
40✔
UNCOV
200
        this.comboAPI.disableTransitions = true;
×
201
    };
202

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

212
        this.close();
×
213
    }
214

215
    private handleSpace() {
UNCOV
216
        if (this.isAddItemFocused()) {
×
UNCOV
217
            return;
×
218
        } else {
UNCOV
219
            this.selectItem(this.focusedItem);
×
220
        }
221
    }
222

223
    private isAddItemFocused(): boolean {
UNCOV
224
        return this.focusedItem instanceof IgxComboAddItemComponent;
×
225
    }
226

227
    private focusAddItemButton() {
UNCOV
228
        if (this.combo.isAddButtonVisible()) {
×
229
            this.focusedItem = this.items[this.items.length - 1];
×
230
        }
231
    }
232
}
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

© 2025 Coveralls, Inc