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

IgniteUI / igniteui-angular / 23353730325

20 Mar 2026 05:03PM UTC coverage: 9.784% (-79.5%) from 89.264%
23353730325

Pull #17069

github

web-flow
Merge cfa7e86d1 into a4dc50177
Pull Request #17069: fix(IgxGrid): Do not apply width constraint to groups.

921 of 16963 branches covered (5.43%)

Branch coverage included in aggregate %.

1 of 3 new or added lines in 1 file covered. (33.33%)

25213 existing lines in 340 files now uncovered.

3842 of 31721 relevant lines covered (12.11%)

6.13 hits per line

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

9.86
/projects/igniteui-angular/list/src/list/list.component.ts
1
import { NgTemplateOutlet } from '@angular/common';
2
import {
3
    Component,
4
    ContentChild,
5
    ContentChildren,
6
    ElementRef,
7
    EventEmitter,
8
    forwardRef,
9
    HostBinding,
10
    Input,
11
    Output,
12
    QueryList,
13
    TemplateRef,
14
    ViewChild,
15
    Directive,
16
    booleanAttribute,
17
    inject,
18
    DestroyRef
19
} from '@angular/core';
20

21

22

23
import { IgxListItemComponent } from './list-item.component';
24
import {
25
    IgxListBaseDirective,
26
    IgxDataLoadingTemplateDirective,
27
    IgxEmptyListTemplateDirective,
28
    IgxListPanState,
29
    IgxListItemLeftPanningTemplateDirective,
30
    IgxListItemRightPanningTemplateDirective
31
} from './list.common';
32
import { IBaseEventArgs } from 'igniteui-angular/core';
33
import { IListResourceStrings, ListResourceStringsEN } from 'igniteui-angular/core';
34
import { getCurrentResourceStrings, onResourceChangeHandle } from 'igniteui-angular/core';
35

36
let NEXT_ID = 0;
3✔
37

38
/**
39
 * Interface for the panStateChange igxList event arguments
40
 */
41
export interface IPanStateChangeEventArgs extends IBaseEventArgs {
42
    oldState: IgxListPanState;
43
    newState: IgxListPanState;
44
    item: IgxListItemComponent;
45
}
46

47
/**
48
 * Interface for the listItemClick igxList event arguments
49
 */
50
export interface IListItemClickEventArgs extends IBaseEventArgs {
51
    item: IgxListItemComponent;
52
    event: Event;
53
    direction: IgxListPanState;
54
}
55

56
/**
57
 * Interface for the listItemPanning igxList event arguments
58
 */
59
export interface IListItemPanningEventArgs extends IBaseEventArgs {
60
    item: IgxListItemComponent;
61
    direction: IgxListPanState;
62
    keepItem: boolean;
63
}
64

65
/**
66
 * igxListThumbnail is container for the List media
67
 * Use it to wrap anything you want to be used as a thumbnail.
68
 */
69
@Directive({
70
    selector: '[igxListThumbnail]',
71
    standalone: true
72
})
73
export class IgxListThumbnailDirective { }
3✔
74

75
/**
76
 * igxListAction is container for the List action
77
 * Use it to wrap anything you want to be used as a list action: icon, checkbox...
78
 */
79
@Directive({
80
    selector: '[igxListAction]',
81
    standalone: true
82
})
83
export class IgxListActionDirective { }
3✔
84

85
/**
86
 * igxListLine is container for the List text content
87
 * Use it to wrap anything you want to be used as a plane text.
88
 */
89
@Directive({
90
    selector: '[igxListLine]',
91
    standalone: true
92
})
93
export class IgxListLineDirective { }
3✔
94

95
/**
96
 * igxListLineTitle is a directive that add class to the target element
97
 * Use it to make anything to look like list Title.
98
 */
99
@Directive({
100
    selector: '[igxListLineTitle]',
101
    standalone: true
102
})
103
export class IgxListLineTitleDirective {
3✔
104
    @HostBinding('class.igx-list__item-line-title')
UNCOV
105
    public cssClass = 'igx-list__item-line-title';
×
106
}
107

108
/**
109
 * igxListLineSubTitle is a directive that add class to the target element
110
 * Use it to make anything to look like list Subtitle.
111
 */
112
@Directive({
113
    selector: '[igxListLineSubTitle]',
114
    standalone: true
115
})
116
export class IgxListLineSubTitleDirective {
3✔
117
    @HostBinding('class.igx-list__item-line-subtitle')
UNCOV
118
    public cssClass = 'igx-list__item-line-subtitle';
×
119
}
120

121
/**
122
 * Displays a collection of data items in a templatable list format
123
 *
124
 * @igxModule IgxListModule
125
 *
126
 * @igxTheme igx-list-theme
127
 *
128
 * @igxKeywords list, data
129
 *
130
 * @igxGroup Grids & Lists
131
 *
132
 * @remarks
133
 * The Ignite UI List displays rows of items and supports one or more header items as well as search and filtering
134
 * of list items. Each list item is completely templatable and will support any valid HTML or Angular component.
135
 *
136
 * @example
137
 * ```html
138
 * <igx-list>
139
 *   <igx-list-item isHeader="true">Contacts</igx-list-item>
140
 *   <igx-list-item *ngFor="let contact of contacts">
141
 *     <span class="name">{{ contact.name }}</span>
142
 *     <span class="phone">{{ contact.phone }}</span>
143
 *   </igx-list-item>
144
 * </igx-list>
145
 * ```
146
 */
147
@Component({
148
    selector: 'igx-list',
149
    templateUrl: 'list.component.html',
150
    providers: [{ provide: IgxListBaseDirective, useExisting: IgxListComponent }],
151
    imports: [NgTemplateOutlet]
152
})
153
export class IgxListComponent extends IgxListBaseDirective {
3✔
UNCOV
154
    public element = inject(ElementRef);
×
UNCOV
155
    private destroyRef = inject(DestroyRef);
×
156

157
    /**
158
     * Returns a collection of all items and headers in the list.
159
     *
160
     * @example
161
     * ```typescript
162
     * let listChildren: QueryList = this.list.children;
163
     * ```
164
     */
UNCOV
165
    @ContentChildren(forwardRef(() => IgxListItemComponent), { descendants: true })
×
166
    public override children: QueryList<IgxListItemComponent>;
167

168
    /**
169
     * Sets/gets the empty list template.
170
     *
171
     * @remarks
172
     * This template is used by IgxList in case there are no list items
173
     * defined and `isLoading` is set to `false`.
174
     *
175
     * @example
176
     * ```html
177
     * <igx-list>
178
     *   <ng-template igxEmptyList>
179
     *     <p class="empty">No contacts! :(</p>
180
     *   </ng-template>
181
     * </igx-list>
182
     * ```
183
     * ```typescript
184
     * let emptyTemplate = this.list.emptyListTemplate;
185
     * ```
186
     */
187
    @ContentChild(IgxEmptyListTemplateDirective, { read: IgxEmptyListTemplateDirective })
188
    public emptyListTemplate: IgxEmptyListTemplateDirective;
189

190
    /**
191
     * Sets/gets the list loading template.
192
     *
193
     * @remarks
194
     * This template is used by IgxList in case there are no list items defined and `isLoading` is set to `true`.
195
     *
196
     * @example
197
     * ```html
198
     * <igx-list>
199
     *   <ng-template igxDataLoading>
200
     *     <p>Patience, we are currently loading your data...</p>
201
     *   </ng-template>
202
     * </igx-list>
203
     * ```
204
     * ```typescript
205
     * let loadingTemplate = this.list.dataLoadingTemplate;
206
     * ```
207
     */
208
    @ContentChild(IgxDataLoadingTemplateDirective, { read: IgxDataLoadingTemplateDirective })
209
    public dataLoadingTemplate: IgxDataLoadingTemplateDirective;
210

211
    /**
212
     * Sets/gets the template for left panning a list item.
213
     *
214
     * @remarks
215
     * Default value is `null`.
216
     *
217
     * @example
218
     * ```html
219
     * <igx-list [allowLeftPanning]="true">
220
     *   <ng-template igxListItemLeftPanning>
221
     *     <igx-icon>delete</igx-icon>Delete
222
     *   </ng-template>
223
     * </igx-list>
224
     * ```
225
     * ```typescript
226
     * let itemLeftPanTmpl = this.list.listItemLeftPanningTemplate;
227
     * ```
228
     */
229
    @ContentChild(IgxListItemLeftPanningTemplateDirective, { read: IgxListItemLeftPanningTemplateDirective })
230
    public override listItemLeftPanningTemplate: IgxListItemLeftPanningTemplateDirective;
231

232
    /**
233
     * Sets/gets the template for right panning a list item.
234
     *
235
     * @remarks
236
     * Default value is `null`.
237
     *
238
     * @example
239
     * ```html
240
     * <igx-list [allowRightPanning] = "true">
241
     *   <ng-template igxListItemRightPanning>
242
     *     <igx-icon>call</igx-icon>Dial
243
     *   </ng-template>
244
     * </igx-list>
245
     * ```
246
     * ```typescript
247
     * let itemRightPanTmpl = this.list.listItemRightPanningTemplate;
248
     * ```
249
     */
250
    @ContentChild(IgxListItemRightPanningTemplateDirective, { read: IgxListItemRightPanningTemplateDirective })
251
    public override listItemRightPanningTemplate: IgxListItemRightPanningTemplateDirective;
252

253
    /**
254
     * Provides a threshold after which the item's panning will be completed automatically.
255
     *
256
     * @remarks
257
     * By default this property is set to 0.5 which is 50% of the list item's width.
258
     *
259
     * @example
260
     * ```html
261
     * <igx-list [panEndTriggeringThreshold]="0.8"></igx-list>
262
     * ```
263
     */
264
    @Input()
UNCOV
265
    public override panEndTriggeringThreshold = 0.5;
×
266

267
    /**
268
     * Sets/gets the `id` of the list.
269
     *
270
     * @remarks
271
     * If not set, the `id` of the first list component will be `"igx-list-0"`.
272
     *
273
     * @example
274
     * ```html
275
     * <igx-list id="my-first-list"></igx-list>
276
     * ```
277
     * ```typescript
278
     * let listId = this.list.id;
279
     * ```
280
     */
281
    @HostBinding('attr.id')
282
    @Input()
UNCOV
283
    public id = `igx-list-${NEXT_ID++}`;
×
284

285
    /**
286
     * Sets/gets whether the left panning of an item is allowed.
287
     *
288
     * @remarks
289
     * Default value is `false`.
290
     *
291
     * @example
292
     * ```html
293
     * <igx-list [allowLeftPanning]="true"></igx-list>
294
     * ```
295
     * ```typescript
296
     * let isLeftPanningAllowed = this.list.allowLeftPanning;
297
     * ```
298
     */
299
    @Input({ transform: booleanAttribute })
UNCOV
300
    public override allowLeftPanning = false;
×
301

302
    /**
303
     * Sets/gets whether the right panning of an item is allowed.
304
     *
305
     * @remarks
306
     * Default value is `false`.
307
     *
308
     * @example
309
     * ```html
310
     * <igx-list [allowRightPanning]="true"></igx-list>
311
     * ```
312
     * ```typescript
313
     * let isRightPanningAllowed = this.list.allowRightPanning;
314
     * ```
315
     */
316
    @Input({ transform: booleanAttribute })
UNCOV
317
    public override allowRightPanning = false;
×
318

319
    /**
320
     * Sets/gets whether the list is currently loading data.
321
     *
322
     * @remarks
323
     * Set it to display the dataLoadingTemplate while data is being retrieved.
324
     * Default value is `false`.
325
     *
326
     * @example
327
     * ```html
328
     *  <igx-list [isLoading]="true"></igx-list>
329
     * ```
330
     * ```typescript
331
     * let isLoading = this.list.isLoading;
332
     * ```
333
     */
334
    @Input({ transform: booleanAttribute })
UNCOV
335
    public isLoading = false;
×
336

337
    /**
338
     * Event emitted when a left pan gesture is executed on a list item.
339
     *
340
     * @remarks
341
     * Provides a reference to an object of type `IListItemPanningEventArgs` as an event argument.
342
     *
343
     * @example
344
     * ```html
345
     * <igx-list [allowLeftPanning]="true" (leftPan)="leftPan($event)"></igx-list>
346
     * ```
347
     */
348
    @Output()
UNCOV
349
    public override leftPan = new EventEmitter<IListItemPanningEventArgs>();
×
350

351
    /**
352
     * Event emitted when a right pan gesture is executed on a list item.
353
     *
354
     * @remarks
355
     * Provides a reference to an object of type `IListItemPanningEventArgs` as an event argument.
356
     *
357
     * @example
358
     * ```html
359
     * <igx-list [allowRightPanning]="true" (rightPan)="rightPan($event)"></igx-list>
360
     * ```
361
     */
362
    @Output()
UNCOV
363
    public override rightPan = new EventEmitter<IListItemPanningEventArgs>();
×
364

365
    /**
366
     * Event emitted when a pan gesture is started.
367
     *
368
     * @remarks
369
     * Provides a reference to an object of type `IListItemPanningEventArgs` as an event argument.
370
     *
371
     * @example
372
     * ```html
373
     * <igx-list (startPan)="startPan($event)"></igx-list>
374
     * ```
375
     */
376
    @Output()
UNCOV
377
    public override startPan = new EventEmitter<IListItemPanningEventArgs>();
×
378

379
    /**
380
     * Event emitted when a pan gesture is completed or canceled.
381
     *
382
     * @remarks
383
     * Provides a reference to an object of type `IListItemPanningEventArgs` as an event argument.
384
     *
385
     * @example
386
     * ```html
387
     * <igx-list (endPan)="endPan($event)"></igx-list>
388
     * ```
389
     */
390
    @Output()
UNCOV
391
    public override endPan = new EventEmitter<IListItemPanningEventArgs>();
×
392

393
    /**
394
     * Event emitted when a pan item is returned to its original position.
395
     *
396
     * @remarks
397
     * Provides a reference to an object of type `IgxListComponent` as an event argument.
398
     *
399
     * @example
400
     * ```html
401
     * <igx-list (resetPan)="resetPan($event)"></igx-list>
402
     * ```
403
     */
404
    @Output()
UNCOV
405
    public override resetPan = new EventEmitter<IgxListComponent>();
×
406

407
    /**
408
     *
409
     * Event emitted when a pan gesture is executed on a list item.
410
     *
411
     * @remarks
412
     * Provides references to the `IgxListItemComponent` and `IgxListPanState` as event arguments.
413
     *
414
     * @example
415
     * ```html
416
     * <igx-list (panStateChange)="panStateChange($event)"></igx-list>
417
     * ```
418
     */
419
    @Output()
UNCOV
420
    public override panStateChange = new EventEmitter<IPanStateChangeEventArgs>();
×
421

422
    /**
423
     * Event emitted when a list item is clicked.
424
     *
425
     * @remarks
426
     * Provides references to the `IgxListItemComponent` and `Event` as event arguments.
427
     *
428
     * @example
429
     * ```html
430
     * <igx-list (itemClicked)="onItemClicked($event)"></igx-list>
431
     * ```
432
     */
433
    @Output()
UNCOV
434
    public override itemClicked = new EventEmitter<IListItemClickEventArgs>();
×
435

436
    /**
437
     * @hidden
438
     * @internal
439
     */
440
    @ViewChild('defaultEmptyList', { read: TemplateRef, static: true })
441
    protected defaultEmptyListTemplate: TemplateRef<any>;
442

443
    /**
444
     * @hidden
445
     * @internal
446
     */
447
    @ViewChild('defaultDataLoading', { read: TemplateRef, static: true })
448
    protected defaultDataLoadingTemplate: TemplateRef<any>;
449

UNCOV
450
    private _resourceStrings: IListResourceStrings = null;
×
UNCOV
451
    private _defaultResourceStrings = getCurrentResourceStrings(ListResourceStringsEN);
×
452

453
    /**
454
     * Sets the resource strings.
455
     * By default it uses EN resources.
456
     */
457
    @Input()
458
    public set resourceStrings(value: IListResourceStrings) {
459
        this._resourceStrings = Object.assign({}, this._resourceStrings, value);
×
460
    }
461

462
    /**
463
     * Returns the resource strings.
464
     */
465
    public get resourceStrings(): IListResourceStrings {
UNCOV
466
        return this._resourceStrings || this._defaultResourceStrings;
×
467
    }
468

469
    constructor() {
UNCOV
470
        super();
×
UNCOV
471
        onResourceChangeHandle(this.destroyRef, () => {
×
472
            this._defaultResourceStrings = getCurrentResourceStrings(ListResourceStringsEN, false);
×
473
        }, this);
474
    }
475

476
    /**
477
     * @hidden
478
     * @internal
479
     */
480
    protected get sortedChildren(): IgxListItemComponent[] {
UNCOV
481
        if (this.children !== undefined) {
×
UNCOV
482
            return this.children.toArray()
×
UNCOV
483
                .sort((a: IgxListItemComponent, b: IgxListItemComponent) => a.index - b.index);
×
484
        }
485
        return null;
×
486
    }
487

UNCOV
488
    private _role = 'list';
×
489

490
    /**
491
     * Gets/Sets the `role` attribute value.
492
     *
493
     * @example
494
     * ```typescript
495
     * let listRole =  this.list.role;
496
     * ```
497
     */
498
    @HostBinding('attr.role')
499
    @Input()
500
    public get role() {
UNCOV
501
        return this._role;
×
502
    }
503

504
    public set role(val: string) {
UNCOV
505
        this._role = val;
×
506
    }
507

508
    /**
509
     * Gets a boolean indicating if the list is empty.
510
     *
511
     * @example
512
     * ```typescript
513
     * let isEmpty =  this.list.isListEmpty;
514
     * ```
515
     */
516
    @HostBinding('class.igx-list--empty')
517
    public get isListEmpty(): boolean {
UNCOV
518
        return !this.children || this.children.length === 0;
×
519
    }
520

521
    /**
522
     * @hidden
523
     * @internal
524
     */
525
    @HostBinding('class.igx-list')
526
    public get cssClass(): boolean {
UNCOV
527
        return !this.isListEmpty;
×
528
    }
529

530
    /**
531
     * Gets the list `items` excluding the header ones.
532
     *
533
     * @example
534
     * ```typescript
535
     * let listItems: IgxListItemComponent[] = this.list.items;
536
     * ```
537
     */
538
    public get items(): IgxListItemComponent[] {
UNCOV
539
        const items: IgxListItemComponent[] = [];
×
UNCOV
540
        if (this.children !== undefined) {
×
UNCOV
541
            for (const child of this.sortedChildren) {
×
UNCOV
542
                if (!child.isHeader) {
×
UNCOV
543
                    items.push(child);
×
544
                }
545
            }
546
        }
UNCOV
547
        return items;
×
548
    }
549

550
    /**
551
     * Gets the header list `items`.
552
     *
553
     * @example
554
     * ```typescript
555
     * let listHeaders: IgxListItemComponent[] =  this.list.headers;
556
     * ```
557
     */
558
    public get headers(): IgxListItemComponent[] {
UNCOV
559
        const headers: IgxListItemComponent[] = [];
×
UNCOV
560
        if (this.children !== undefined) {
×
UNCOV
561
            for (const child of this.children.toArray()) {
×
UNCOV
562
                if (child.isHeader) {
×
UNCOV
563
                    headers.push(child);
×
564
                }
565
            }
566
        }
UNCOV
567
        return headers;
×
568
    }
569

570
    /**
571
     * Gets the `context` object of the template binding.
572
     *
573
     * @remarks
574
     * Gets the `context` object which represents the `template context` binding into the `list container`
575
     * by providing the `$implicit` declaration which is the `IgxListComponent` itself.
576
     *
577
     * @example
578
     * ```typescript
579
     * let listComponent =  this.list.context;
580
     * ```
581
     */
582
    public get context(): any {
UNCOV
583
        return {
×
584
            $implicit: this
585
        };
586
    }
587

588
    /**
589
     * Gets a `TemplateRef` to the currently used template.
590
     *
591
     * @example
592
     * ```typescript
593
     * let listTemplate = this.list.template;
594
     * ```
595
     */
596
    public get template(): TemplateRef<any> {
UNCOV
597
        if (this.isLoading) {
×
UNCOV
598
            return this.dataLoadingTemplate ? this.dataLoadingTemplate.template : this.defaultDataLoadingTemplate;
×
599
        } else {
UNCOV
600
            return this.emptyListTemplate ? this.emptyListTemplate.template : this.defaultEmptyListTemplate;
×
601
        }
602
    }
603
}
604

605
/**
606
 * @hidden
607
 */
608

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