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

IgniteUI / igniteui-angular / 6653488239

26 Oct 2023 11:33AM UTC coverage: 92.101% (-0.1%) from 92.206%
6653488239

push

github

web-flow
Merge pull request #13451 from IgniteUI/bundle-test-extended

refactor(i18n, util): tree shaking i18n

15273 of 17962 branches covered (0.0%)

45 of 45 new or added lines in 24 files covered. (100.0%)

26410 of 28675 relevant lines covered (92.1%)

30213.01 hits per line

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

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

2✔
19

20

21
import { IgxListItemComponent } from './list-item.component';
22
import {
23
    IgxListBaseDirective,
24
    IgxDataLoadingTemplateDirective,
25
    IgxEmptyListTemplateDirective,
26
    IgxListPanState,
27
    IgxListItemLeftPanningTemplateDirective,
28
    IgxListItemRightPanningTemplateDirective
29
} from './list.common';
30
import { IDisplayDensityOptions, DisplayDensityToken } from '../core/density';
2✔
31
import { IBaseEventArgs } from '../core/utils';
32
import { IListResourceStrings, ListResourceStringsEN } from '../core/i18n/list-resources';
2✔
33
import { getCurrentResourceStrings } from '../core/i18n/resources';
34

35
let NEXT_ID = 0;
36

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

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

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

64
/**
65
 * igxListThumbnail is container for the List media
66
 * Use it to wrap anything you want to be used as a thumbnail.
2✔
67
 */
68
@Directive({
69
    // eslint-disable-next-line @angular-eslint/directive-selector
70
    selector: '[igxListThumbnail]',
71
    standalone: true
72
})
73
export class IgxListThumbnailDirective {}
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
 */
2✔
79
@Directive({
80
    // eslint-disable-next-line @angular-eslint/directive-selector
5✔
81
    selector: '[igxListAction]',
82
    standalone: true
2✔
83
})
84
export class IgxListActionDirective {}
85

86
/**
2✔
87
 * igxListLine is container for the List text content
88
 * Use it to wrap anything you want to be used as a plane text.
89
 */
90
@Directive({
91
    // eslint-disable-next-line @angular-eslint/directive-selector
92
    selector: '[igxListLine]',
93
    standalone: true
94
})
95
export class IgxListLineDirective {}
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
    // eslint-disable-next-line @angular-eslint/directive-selector
103
    selector: '[igxListLineTitle]',
104
    standalone: true
105
})
106
export class IgxListLineTitleDirective {
107
    @HostBinding('class.igx-list__item-line-title')
108
    public cssClass = 'igx-list__item-line-title';
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
    // eslint-disable-next-line @angular-eslint/directive-selector
117
    selector: '[igxListLineSubTitle]',
118
    standalone: true
119
})
120
export class IgxListLineSubTitleDirective {
2✔
121
    @HostBinding('class.igx-list__item-line-subtitle')
122
    public cssClass = 'igx-list__item-line-subtitle';
×
123
}
124

125
/**
126
 * Displays a collection of data items in a templatable list format
127
 *
128
 * @igxModule IgxListModule
17✔
129
 *
130
 * @igxTheme igx-list-theme
131
 *
701✔
132
 * @igxKeywords list, data
701✔
133
 *
701✔
134
 * @igxGroup Grids & Lists
701✔
135
 *
701✔
136
 * @remarks
701✔
137
 * The Ignite UI List displays rows of items and supports one or more header items as well as search and filtering
701✔
138
 * of list items. Each list item is completely templatable and will support any valid HTML or Angular component.
701✔
139
 *
701✔
140
 * @example
701✔
141
 * ```html
701✔
142
 * <igx-list>
701✔
143
 *   <igx-list-item isHeader="true">Contacts</igx-list-item>
701✔
144
 *   <igx-list-item *ngFor="let contact of contacts">
701✔
145
 *     <span class="name">{{ contact.name }}</span>
701✔
146
 *     <span class="phone">{{ contact.phone }}</span>
147
 *   </igx-list-item>
148
 * </igx-list>
149
 * ```
150
 */
151
@Component({
152
    selector: 'igx-list',
91!
153
    templateUrl: 'list.component.html',
91✔
154
    providers: [{ provide: IgxListBaseDirective, useExisting: IgxListComponent }],
258✔
155
    standalone: true,
156
    imports: [NgIf, NgTemplateOutlet]
×
157
})
158
export class IgxListComponent extends IgxListBaseDirective {
159
    /**
7,506✔
160
     * Returns a collection of all items and headers in the list.
161
     *
162
     * @example
22,530✔
163
     * ```typescript
164
     * let listChildren: QueryList = this.list.children;
165
     * ```
7,512✔
166
     */
167
    @ContentChildren(forwardRef(() => IgxListItemComponent), { descendants: true })
168
    public override children: QueryList<IgxListItemComponent>;
7,506✔
169

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

452
    private _resourceStrings = getCurrentResourceStrings(ListResourceStringsEN);
453

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

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

470
    constructor(public element: ElementRef,
471
        @Optional() @Inject(DisplayDensityToken) _displayDensityOptions: IDisplayDensityOptions) {
472
        super(_displayDensityOptions, element);
473
    }
474

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

487
    /**
488
     * Gets the `role` attribute value.
489
     *
490
     * @example
491
     * ```typescript
492
     * let listRole =  this.list.role;
493
     * ```
494
     */
495
    @HostBinding('attr.role')
496
    public get role() {
497
        return 'list';
498
    }
499

500
    /**
501
     * Gets a boolean indicating if the list is empty.
502
     *
503
     * @example
504
     * ```typescript
505
     * let isEmpty =  this.list.isListEmpty;
506
     * ```
507
     */
508
    @HostBinding('class.igx-list--empty')
509
    public get isListEmpty(): boolean {
510
        return !this.children || this.children.length === 0;
511
    }
512

513
    /**
514
     * @hidden
515
     * @internal
516
     */
517
    @HostBinding('class.igx-list')
518
    public get cssClass(): boolean {
519
        return !this.isListEmpty;
520
    }
521

522
    /** @hidden @internal */
523
    @HostBinding('style.--component-size')
524
    public get componentSize() {
525
        if (!this.isListEmpty) {
526
            return this.getComponentSizeStyles();
527
        }
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[] {
539
        const items: IgxListItemComponent[] = [];
540
        if (this.children !== undefined) {
541
            for (const child of this.sortedChildren) {
542
                if (!child.isHeader) {
543
                    items.push(child);
544
                }
545
            }
546
        }
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[] {
559
        const headers: IgxListItemComponent[] = [];
560
        if (this.children !== undefined) {
561
            for (const child of this.children.toArray()) {
562
                if (child.isHeader) {
563
                    headers.push(child);
564
                }
565
            }
566
        }
567
        return headers;
568
    }
569

570
    /**
571
     * Gets the `context` object of the template binding.
572
     *
573
     * @remark
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 {
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> {
597
        if (this.isLoading) {
598
            return this.dataLoadingTemplate ? this.dataLoadingTemplate.template : this.defaultDataLoadingTemplate;
599
        } else {
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