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

IgniteUI / igniteui-angular / 30891705717

04 Aug 2026 08:22AM UTC coverage: 90.16% (-0.03%) from 90.187%
30891705717

Pull #15125

github

web-flow
Merge 19b57fb2e into 0a0755cbb
Pull Request #15125: refactor(*): bundle styles with components

14975 of 17448 branches covered (85.83%)

Branch coverage included in aggregate %.

30133 of 32583 relevant lines covered (92.48%)

37490.31 hits per line

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

97.18
/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
    ChangeDetectionStrategy,
20
    ViewEncapsulation
21
} from '@angular/core';
22

23

24

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

38
let NEXT_ID = 0;
3✔
39

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

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

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

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

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

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

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

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

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

164
    /**
165
     * Returns a collection of all items and headers in the list.
166
     *
167
     * @example
168
     * ```typescript
169
     * let listChildren: QueryList = this.list.children;
170
     * ```
171
     */
172
    @ContentChildren(forwardRef(() => IgxListItemComponent), { descendants: true })
6✔
173
    public override children: QueryList<IgxListItemComponent>;
174

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

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

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

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

260
    /**
261
     * Provides a threshold after which the item's panning will be completed automatically.
262
     *
263
     * @remarks
264
     * By default this property is set to 0.5 which is 50% of the list item's width.
265
     *
266
     * @example
267
     * ```html
268
     * <igx-list [panEndTriggeringThreshold]="0.8"></igx-list>
269
     * ```
270
     */
271
    @Input()
272
    public override panEndTriggeringThreshold = 0.5;
889✔
273

274
    /**
275
     * Sets/gets the `id` of the list.
276
     *
277
     * @remarks
278
     * If not set, the `id` of the first list component will be `"igx-list-0"`.
279
     *
280
     * @example
281
     * ```html
282
     * <igx-list id="my-first-list"></igx-list>
283
     * ```
284
     * ```typescript
285
     * let listId = this.list.id;
286
     * ```
287
     */
288
    @HostBinding('attr.id')
289
    @Input()
290
    public id = `igx-list-${NEXT_ID++}`;
889✔
291

292
    /**
293
     * Sets/gets whether the left panning of an item is allowed.
294
     *
295
     * @remarks
296
     * Default value is `false`.
297
     *
298
     * @example
299
     * ```html
300
     * <igx-list [allowLeftPanning]="true"></igx-list>
301
     * ```
302
     * ```typescript
303
     * let isLeftPanningAllowed = this.list.allowLeftPanning;
304
     * ```
305
     */
306
    @Input({ transform: booleanAttribute })
307
    public override allowLeftPanning = false;
889✔
308

309
    /**
310
     * Sets/gets whether the right panning of an item is allowed.
311
     *
312
     * @remarks
313
     * Default value is `false`.
314
     *
315
     * @example
316
     * ```html
317
     * <igx-list [allowRightPanning]="true"></igx-list>
318
     * ```
319
     * ```typescript
320
     * let isRightPanningAllowed = this.list.allowRightPanning;
321
     * ```
322
     */
323
    @Input({ transform: booleanAttribute })
324
    public override allowRightPanning = false;
889✔
325

326
    /**
327
     * Sets/gets whether the list is currently loading data.
328
     *
329
     * @remarks
330
     * Set it to display the dataLoadingTemplate while data is being retrieved.
331
     * Default value is `false`.
332
     *
333
     * @example
334
     * ```html
335
     *  <igx-list [isLoading]="true"></igx-list>
336
     * ```
337
     * ```typescript
338
     * let isLoading = this.list.isLoading;
339
     * ```
340
     */
341
    @Input({ transform: booleanAttribute })
342
    public isLoading = false;
889✔
343

344
    /**
345
     * Event emitted when a left pan gesture is executed on a list item.
346
     *
347
     * @remarks
348
     * Provides a reference to an object of type `IListItemPanningEventArgs` as an event argument.
349
     *
350
     * @example
351
     * ```html
352
     * <igx-list [allowLeftPanning]="true" (leftPan)="leftPan($event)"></igx-list>
353
     * ```
354
     */
355
    @Output()
356
    public override leftPan = new EventEmitter<IListItemPanningEventArgs>();
889✔
357

358
    /**
359
     * Event emitted when a right pan gesture is executed on a list item.
360
     *
361
     * @remarks
362
     * Provides a reference to an object of type `IListItemPanningEventArgs` as an event argument.
363
     *
364
     * @example
365
     * ```html
366
     * <igx-list [allowRightPanning]="true" (rightPan)="rightPan($event)"></igx-list>
367
     * ```
368
     */
369
    @Output()
370
    public override rightPan = new EventEmitter<IListItemPanningEventArgs>();
889✔
371

372
    /**
373
     * Event emitted when a pan gesture is started.
374
     *
375
     * @remarks
376
     * Provides a reference to an object of type `IListItemPanningEventArgs` as an event argument.
377
     *
378
     * @example
379
     * ```html
380
     * <igx-list (startPan)="startPan($event)"></igx-list>
381
     * ```
382
     */
383
    @Output()
384
    public override startPan = new EventEmitter<IListItemPanningEventArgs>();
889✔
385

386
    /**
387
     * Event emitted when a pan gesture is completed or canceled.
388
     *
389
     * @remarks
390
     * Provides a reference to an object of type `IListItemPanningEventArgs` as an event argument.
391
     *
392
     * @example
393
     * ```html
394
     * <igx-list (endPan)="endPan($event)"></igx-list>
395
     * ```
396
     */
397
    @Output()
398
    public override endPan = new EventEmitter<IListItemPanningEventArgs>();
889✔
399

400
    /**
401
     * Event emitted when a pan item is returned to its original position.
402
     *
403
     * @remarks
404
     * Provides a reference to an object of type list as an event argument.
405
     *
406
     * @example
407
     * ```html
408
     * <igx-list (resetPan)="resetPan($event)"></igx-list>
409
     * ```
410
     */
411
    @Output()
412
    public override resetPan = new EventEmitter<IgxListComponent>();
889✔
413

414
    /**
415
     *
416
     * Event emitted when a pan gesture is executed on a list item.
417
     *
418
     * @remarks
419
     * Provides references to the list item and list pan state as event arguments.
420
     *
421
     * @example
422
     * ```html
423
     * <igx-list (panStateChange)="panStateChange($event)"></igx-list>
424
     * ```
425
     */
426
    @Output()
427
    public override panStateChange = new EventEmitter<IPanStateChangeEventArgs>();
889✔
428

429
    /**
430
     * Event emitted when a list item is clicked.
431
     *
432
     * @remarks
433
     * Provides references to the list item and `Event` as event arguments.
434
     *
435
     * @example
436
     * ```html
437
     * <igx-list (itemClicked)="onItemClicked($event)"></igx-list>
438
     * ```
439
     */
440
    @Output()
441
    public override itemClicked = new EventEmitter<IListItemClickEventArgs>();
889✔
442

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

450
    /**
451
     * @hidden
452
     * @internal
453
     */
454
    @ViewChild('defaultDataLoading', { read: TemplateRef, static: true })
455
    protected defaultDataLoadingTemplate: TemplateRef<any>;
456

457
    private _resourceStrings: IListResourceStrings = null;
889✔
458
    private _defaultResourceStrings = getCurrentResourceStrings(ListResourceStringsEN);
889✔
459

460
    /**
461
     * Sets the resource strings.
462
     * By default it uses EN resources.
463
     */
464
    @Input()
465
    public set resourceStrings(value: IListResourceStrings) {
466
        this._resourceStrings = Object.assign({}, this._resourceStrings, value);
×
467
    }
468

469
    /**
470
     * Returns the resource strings.
471
     */
472
    public get resourceStrings(): IListResourceStrings {
473
        return this._resourceStrings || this._defaultResourceStrings;
21✔
474
    }
475

476
    constructor() {
477
        super();
889✔
478
        onResourceChangeHandle(this.destroyRef, () => {
889✔
479
            this._defaultResourceStrings = getCurrentResourceStrings(ListResourceStringsEN, false);
7✔
480
        }, this);
481
    }
482

483
    /**
484
     * @hidden
485
     * @internal
486
     */
487
    protected get sortedChildren(): IgxListItemComponent[] {
488
        if (this.children !== undefined) {
92✔
489
            return this.children.toArray()
92✔
490
                .sort((a: IgxListItemComponent, b: IgxListItemComponent) => a.index - b.index);
334✔
491
        }
492
        return null;
×
493
    }
494

495
    private _role = 'list';
889✔
496

497
    /**
498
     * Gets/Sets the `role` attribute value.
499
     *
500
     * @example
501
     * ```typescript
502
     * let listRole =  this.list.role;
503
     * ```
504
     */
505
    @HostBinding('attr.role')
506
    @Input()
507
    public get role() {
508
        return this._role;
11,615✔
509
    }
510

511
    public set role(val: string) {
512
        this._role = val;
531✔
513
    }
514

515
    /**
516
     * @hidden
517
     * @internal
518
     *
519
     */
520
    @HostBinding('class.igx-list')
521
    public cssClass = 'igx-list';
889✔
522

523
    /**
524
     * Gets a boolean indicating if the list is empty.
525
     *
526
     * @example
527
     * ```typescript
528
     * let isEmpty =  this.list.isListEmpty;
529
     * ```
530
     */
531
    @HostBinding('class.igx-list--empty')
532
    public get isListEmpty(): boolean {
533
        return !this.children || this.children.length === 0;
11,621✔
534
    }
535

536
    /**
537
     * Gets the list `items` excluding the header ones.
538
     *
539
     * @example
540
     * ```typescript
541
     * let listItems: IgxListItemComponent[] = this.list.items;
542
     * ```
543
     */
544
    public get items(): IgxListItemComponent[] {
545
        const items: IgxListItemComponent[] = [];
97✔
546
        if (this.children !== undefined) {
97✔
547
            for (const child of this.sortedChildren) {
92✔
548
                if (!child.isHeader) {
330✔
549
                    items.push(child);
261✔
550
                }
551
            }
552
        }
553
        return items;
97✔
554
    }
555

556
    /**
557
     * Gets the header list `items`.
558
     *
559
     * @example
560
     * ```typescript
561
     * let listHeaders: IgxListItemComponent[] =  this.list.headers;
562
     * ```
563
     */
564
    public get headers(): IgxListItemComponent[] {
565
        const headers: IgxListItemComponent[] = [];
11✔
566
        if (this.children !== undefined) {
11✔
567
            for (const child of this.children.toArray()) {
9✔
568
                if (child.isHeader) {
38✔
569
                    headers.push(child);
11✔
570
                }
571
            }
572
        }
573
        return headers;
11✔
574
    }
575

576
    /**
577
     * Gets the `context` object of the template binding.
578
     *
579
     * @remarks
580
     * Gets the `context` object which represents the `template context` binding into the `list container`
581
     * by providing the `$implicit` declaration which is the list itself.
582
     *
583
     * @example
584
     * ```typescript
585
     * let listComponent =  this.list.context;
586
     * ```
587
     */
588
    public get context(): any {
589
        return {
7,899✔
590
            $implicit: this
591
        };
592
    }
593

594
    /**
595
     * Gets a `TemplateRef` to the currently used template.
596
     *
597
     * @example
598
     * ```typescript
599
     * let listTemplate = this.list.template;
600
     * ```
601
     */
602
    public get template(): TemplateRef<any> {
603
        if (this.isLoading) {
7,899✔
604
            return this.dataLoadingTemplate ? this.dataLoadingTemplate.template : this.defaultDataLoadingTemplate;
7,856✔
605
        } else {
606
            return this.emptyListTemplate ? this.emptyListTemplate.template : this.defaultEmptyListTemplate;
43✔
607
        }
608
    }
609
}
610

611
/**
612
 * @hidden
613
 */
614

STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc