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

IgniteUI / igniteui-angular / 13561607909

27 Feb 2025 08:03AM UTC coverage: 91.644% (+0.003%) from 91.641%
13561607909

push

github

web-flow
fix(grid): Update grid cell active state selector specificity (#15402)

13328 of 15596 branches covered (85.46%)

26882 of 29333 relevant lines covered (91.64%)

33708.8 hits per line

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

97.21
/projects/igniteui-angular/src/lib/grids/columns/column.component.ts
1
import { Subject } from 'rxjs';
2
import {
3
    AfterContentInit,
4
    ChangeDetectorRef,
5
    ChangeDetectionStrategy,
6
    Component,
7
    ContentChild,
8
    ContentChildren,
9
    Input,
10
    QueryList,
11
    TemplateRef,
12
    Output,
13
    EventEmitter,
14
    OnDestroy,
15
    Inject,
16
    Optional,
17
    Self,
18
    booleanAttribute,
19
} from '@angular/core';
20
import { notifyChanges } from '../watch-changes';
21
import { WatchColumnChanges } from '../watch-changes';
22
import { GridColumnDataType } from '../../data-operations/data-util';
23
import {
24
    IgxFilteringOperand,
25
    IgxBooleanFilteringOperand,
26
    IgxNumberFilteringOperand,
27
    IgxDateFilteringOperand,
28
    IgxStringFilteringOperand,
29
    IgxDateTimeFilteringOperand,
30
    IgxTimeFilteringOperand
31
} from '../../data-operations/filtering-condition';
32
import { ISortingStrategy, DefaultSortingStrategy } from '../../data-operations/sorting-strategy';
33
import { IgxRowDirective } from '../row.directive';
34
import { FilteringExpressionsTree } from '../../data-operations/filtering-expressions-tree';
35
import { CellType, ColumnType, GridType, IgxCellTemplateContext, IgxColumnTemplateContext, IgxSummaryTemplateContext, IGX_GRID_BASE } from '../common/grid.interface';
36
import { IgxGridHeaderComponent } from '../headers/grid-header.component';
37
import { IgxGridFilteringCellComponent } from '../filtering/base/grid-filtering-cell.component';
38
import { IgxGridHeaderGroupComponent } from '../headers/grid-header-group.component';
39
import {
40
    IgxSummaryOperand, IgxNumberSummaryOperand, IgxDateSummaryOperand,
41
    IgxSummaryResult, IgxTimeSummaryOperand
42
} from '../summaries/grid-summary';
43
import {
44
    IgxCellTemplateDirective,
45
    IgxCellHeaderTemplateDirective,
46
    IgxCellEditorTemplateDirective,
47
    IgxCollapsibleIndicatorTemplateDirective,
48
    IgxFilterCellTemplateDirective,
49
    IgxSummaryTemplateDirective,
50
    IgxCellValidationErrorDirective
51
} from './templates.directive';
52
import { MRLResizeColumnInfo, MRLColumnSizeInfo, IColumnPipeArgs, IColumnEditorOptions } from './interfaces';
53
import { DropPosition } from '../moving/moving.service';
54
import { IColumnVisibilityChangingEventArgs, IPinColumnCancellableEventArgs, IPinColumnEventArgs } from '../common/events';
55
import { isConstructor, PlatformUtil } from '../../core/utils';
56
import { IgxGridCell } from '../grid-public-cell';
57
import { NG_VALIDATORS, Validator } from '@angular/forms';
58
import { Size } from '../common/enums';
59
import { ExpressionsTreeUtil } from '../../data-operations/expressions-tree-util';
60

61
const DEFAULT_DATE_FORMAT = 'mediumDate';
2✔
62
const DEFAULT_TIME_FORMAT = 'mediumTime';
2✔
63
const DEFAULT_DATE_TIME_FORMAT = 'medium';
2✔
64
const DEFAULT_DIGITS_INFO = '1.0-3';
2✔
65

66
/* blazorElement */
67
/* contentParent: ColumnGroup */
68
/* wcElementTag: igc-column */
69
/* additionalIdentifier: Field */
70
/* blazorIndirectRender */
71
/**
72
 * **Ignite UI for Angular Column** -
73
 * [Documentation](https://www.infragistics.com/products/ignite-ui-angular/angular/components/grid/grid#columns-configuration)
74
 *
75
 * The Ignite UI Column is used within an `igx-grid` element to define what data the column will show. Features such as sorting,
76
 * filtering & editing are enabled at the column level.  You can also provide a template containing custom content inside
77
 * the column using `ng-template` which will be used for all cells within the column.
78
 *
79
 * @igxParent IgxGridComponent, IgxTreeGridComponent, IgxHierarchicalGridComponent, IgxPivotGridComponent, IgxRowIslandComponent, IgxColumnGroupComponent, IgxColumnLayoutComponent
80
 */
81
@Component({
82
    changeDetection: ChangeDetectionStrategy.OnPush,
83
    selector: 'igx-column',
84
    template: ``,
85
    standalone: true
86
})
87
export class IgxColumnComponent implements AfterContentInit, OnDestroy, ColumnType {
2✔
88
    /**
89
     * Sets/gets the `field` value.
90
     * ```typescript
91
     * let columnField = this.column.field;
92
     * ```
93
     * ```html
94
     * <igx-column [field] = "'ID'"></igx-column>
95
     * ```
96
     *
97
     * @memberof IgxColumnComponent
98
     */
99
    @Input()
100
    public set field(value: string) {
101
        this._field = value;
28,099✔
102
        this.hasNestedPath = value?.includes('.');
28,099✔
103
    }
104
    public get field(): string {
105
        return this._field;
20,772,219✔
106
    }
107

108

109
    /**
110
     * @hidden @internal
111
     */
112
    public validators: Validator[] = [];
29,102✔
113

114
    /**
115
     * Sets/gets the `header` value.
116
     * ```typescript
117
     * let columnHeader = this.column.header;
118
     * ```
119
     * ```html
120
     * <igx-column [header] = "'ID'"></igx-column>
121
     * ```
122
     *
123
     * @memberof IgxColumnComponent
124
     */
125
    @notifyChanges()
126
    @WatchColumnChanges()
127
    @Input()
128
    public header = '';
29,102✔
129
    /**
130
     * Sets/gets the `title` value.
131
     * ```typescript
132
     * let title = this.column.title;
133
     * ```
134
     * ```html
135
     * <igx-column [title] = "'Some column tooltip'"></igx-column>
136
     * ```
137
     *
138
     * @memberof IgxColumnComponent
139
     */
140
    @notifyChanges()
141
    @WatchColumnChanges()
142
    @Input()
143
    public title = '';
29,102✔
144
    /**
145
     * Sets/gets whether the column is sortable.
146
     * Default value is `false`.
147
     * ```typescript
148
     * let isSortable = this.column.sortable;
149
     * ```
150
     * ```html
151
     * <igx-column [sortable] = "true"></igx-column>
152
     * ```
153
     *
154
     * @memberof IgxColumnComponent
155
     */
156
    @WatchColumnChanges()
157
    @Input({ transform: booleanAttribute })
158
    public sortable = false;
29,102✔
159
    /**
160
     * Returns if the column is selectable.
161
     * ```typescript
162
     * let columnSelectable = this.column.selectable;
163
     * ```
164
     *
165
     * @memberof IgxColumnComponent
166
     */
167
    @WatchColumnChanges()
168
    @Input()
169
    public get selectable(): boolean {
170
        return this._selectable;
119,787✔
171
    }
172

173
    /**
174
     * Sets if the column is selectable.
175
     * Default value is `true`.
176
     * ```html
177
     * <igx-column [selectable] = "false"></igx-column>
178
     * ```
179
     *
180
     * @memberof IgxColumnComponent
181
     */
182
    public set selectable(value: boolean) {
183
        this._selectable = value;
1,600✔
184
    }
185

186
    /**
187
     * Sets/gets whether the column is groupable.
188
     * Default value is `false`.
189
     * ```typescript
190
     * let isGroupable = this.column.groupable;
191
     * ```
192
     * ```html
193
     * <igx-column [groupable] = "true"></igx-column>
194
     * ```
195
     *
196
     * @memberof IgxColumnComponent
197
     */
198
    @notifyChanges(true)
199
    @WatchColumnChanges()
200
    @Input({ transform: booleanAttribute })
201
    public get groupable(): boolean {
202
        return this._groupable;
162,473✔
203
    }
204
    public set groupable(value: boolean) {
205
        this._groupable = value;
3,447✔
206
        this.grid.groupablePipeTrigger++;
3,447✔
207
    }
208
    /**
209
     * Gets whether the column is editable.
210
     * Default value is `false`.
211
     * ```typescript
212
     * let isEditable = this.column.editable;
213
     * ```
214
     *
215
     * @memberof IgxColumnComponent
216
     */
217
    @WatchColumnChanges()
218
    @Input({ transform: booleanAttribute })
219
    public get editable(): boolean {
220
        // Updating the primary key when grid has transactions (incl. row edit)
221
        // should not be allowed, as that can corrupt transaction state.
222
        const rowEditable = this.grid && this.grid.rowEditable;
2,402,299✔
223
        const hasTransactions = this.grid && this.grid.transactions.enabled;
2,402,299✔
224

225
        if (this.isPrimaryColumn && (rowEditable || hasTransactions)) {
2,402,299✔
226
            return false;
99,069✔
227
        }
228

229
        if (this._editable !== undefined) {
2,303,230✔
230
            return this._editable;
391,329✔
231
        } else {
232
            return rowEditable;
1,911,901✔
233
        }
234
    }
235
    /**
236
     * Sets whether the column is editable.
237
     * ```typescript
238
     * this.column.editable = true;
239
     * ```
240
     * ```html
241
     * <igx-column [editable] = "true"></igx-column>
242
     * ```
243
     *
244
     * @memberof IgxColumnComponent
245
     */
246
    public set editable(editable: boolean) {
247
        this._editable = editable;
4,424✔
248
    }
249
    /**
250
     * Sets/gets whether the column is filterable.
251
     * Default value is `true`.
252
     * ```typescript
253
     * let isFilterable = this.column.filterable;
254
     * ```
255
     * ```html
256
     * <igx-column [filterable] = "false"></igx-column>
257
     * ```
258
     *
259
     * @memberof IgxColumnComponent
260
     */
261
    @notifyChanges()
262
    @WatchColumnChanges()
263
    @Input({ transform: booleanAttribute })
264
    public filterable = true;
29,102✔
265
    /**
266
     * Sets/gets whether the column is resizable.
267
     * Default value is `false`.
268
     * ```typescript
269
     * let isResizable = this.column.resizable;
270
     * ```
271
     * ```html
272
     * <igx-column [resizable] = "true"></igx-column>
273
     * ```
274
     *
275
     * @memberof IgxColumnComponent
276
     */
277
    @WatchColumnChanges()
278
    @Input({ transform: booleanAttribute })
279
    public resizable = false;
29,102✔
280

281
    /**
282
     * Sets/gets whether the column header is included in autosize logic.
283
     * Useful when template for a column header is sized based on parent, for example a default `div`.
284
     * Default value is `false`.
285
     * ```typescript
286
     * let isResizable = this.column.resizable;
287
     * ```
288
     * ```html
289
     * <igx-column [resizable] = "true"></igx-column>
290
     * ```
291
     *
292
     * @memberof IgxColumnComponent
293
     */
294
    @WatchColumnChanges()
295
    @Input({ transform: booleanAttribute })
296
    public autosizeHeader = true;
29,102✔
297

298
    /**
299
     * Gets a value indicating whether the summary for the column is enabled.
300
     * ```typescript
301
     * let hasSummary = this.column.hasSummary;
302
     * ```
303
     *
304
     * @memberof IgxColumnComponent
305
     */
306
    @notifyChanges(true)
307
    @WatchColumnChanges()
308
    @Input({ transform: booleanAttribute })
309
    public get hasSummary() {
310
        return this._hasSummary;
2,315,880✔
311
    }
312
    /**
313
     * Sets a value indicating whether the summary for the column is enabled.
314
     * Default value is `false`.
315
     * ```html
316
     * <igx-column [hasSummary] = "true"></igx-column>
317
     * ```
318
     *
319
     * @memberof IgxColumnComponent
320
     */
321
    public set hasSummary(value) {
322
        this._hasSummary = value;
3,275✔
323

324
        if (this.grid) {
3,275✔
325
            this.grid.summaryService.resetSummaryHeight();
3,275✔
326
        }
327
    }
328
    /**
329
     * Gets whether the column is hidden.
330
     * ```typescript
331
     * let isHidden = this.column.hidden;
332
     * ```
333
     *
334
     * @memberof IgxColumnComponent
335
     */
336
    @notifyChanges(true)
337
    @WatchColumnChanges()
338
    @Input({ transform: booleanAttribute })
339
    public get hidden(): boolean {
340
        return this._hidden;
1,317,537✔
341
    }
342
    /**
343
     * Sets the column hidden property.
344
     * Default value is `false`.
345
     * ```html
346
     * <igx-column [hidden] = "true"></igx-column>
347
     * ```
348
     *
349
     * Two-way data binding.
350
     * ```html
351
     * <igx-column [(hidden)] = "model.isHidden"></igx-column>
352
     * ```
353
     *
354
     * @memberof IgxColumnComponent
355
     */
356
    public set hidden(value: boolean) {
357
        if (this._hidden !== value) {
5,848✔
358
            this._hidden = value;
1,139✔
359
            this.hiddenChange.emit(this._hidden);
1,139✔
360
            if (this.columnLayoutChild && this.parent.hidden !== value) {
1,139✔
361
                this.parent.hidden = value;
5✔
362
                return;
5✔
363
            }
364
            if (this.grid) {
1,134✔
365
                this.grid.crudService.endEdit(false);
1,134✔
366
                this.grid.summaryService.resetSummaryHeight();
1,134✔
367
                this.grid.filteringService.refreshExpressions();
1,134✔
368
                this.grid.filteringService.hideFilteringRowOnColumnVisibilityChange(this);
1,134✔
369
                this.grid.notifyChanges();
1,134✔
370
            }
371
        }
372
    }
373

374
    /**
375
     * Returns if the column is selected.
376
     * ```typescript
377
     * let isSelected = this.column.selected;
378
     * ```
379
     *
380
     * @memberof IgxColumnComponent
381
     */
382
    public get selected(): boolean {
383
        return this.grid.selectionService.isColumnSelected(this.field);
1,690,782✔
384
    }
385

386
    /**
387
     * Select/deselect a column.
388
     * Default value is `false`.
389
     * ```typescript
390
     * this.column.selected = true;
391
     * ```
392
     *
393
     * @memberof IgxColumnComponent
394
     */
395
    public set selected(value: boolean) {
396
        if (this.selectable && value !== this.selected) {
46✔
397
            if (value) {
42✔
398
                this.grid.selectionService.selectColumnsWithNoEvent([this.field]);
37✔
399
            } else {
400
                this.grid.selectionService.deselectColumnsWithNoEvent([this.field]);
5✔
401
            }
402
            this.grid.notifyChanges();
42✔
403
        }
404
    }
405

406
    /**
407
     * @hidden
408
     */
409
    @Output()
410
    public hiddenChange = new EventEmitter<boolean>();
29,102✔
411

412
    /** @hidden */
413
    @Output()
414
    public expandedChange = new EventEmitter<boolean>();
29,102✔
415

416
    /** @hidden */
417
    @Output()
418
    public collapsibleChange = new EventEmitter<boolean>();
29,102✔
419
    /** @hidden */
420
    @Output()
421
    public visibleWhenCollapsedChange = new EventEmitter<boolean>();
29,102✔
422

423
    /** @hidden */
424
    @Output()
425
    public columnChange = new EventEmitter<void>();
29,102✔
426

427
    /**
428
     * Gets whether the hiding is disabled.
429
     * ```typescript
430
     * let isHidingDisabled =  this.column.disableHiding;
431
     * ```
432
     *
433
     * @memberof IgxColumnComponent
434
     */
435
    @notifyChanges()
436
    @WatchColumnChanges()
437
    @Input({ transform: booleanAttribute })
438
    public disableHiding = false;
29,102✔
439
    /**
440
     * Gets whether the pinning is disabled.
441
     * ```typescript
442
     * let isPinningDisabled =  this.column.disablePinning;
443
     * ```
444
     *
445
     * @memberof IgxColumnComponent
446
     */
447
    @notifyChanges()
448
    @WatchColumnChanges()
449
    @Input({ transform: booleanAttribute })
450
    public disablePinning = false;
29,102✔
451

452
    /**
453
     * Gets the `width` of the column.
454
     * ```typescript
455
     * let columnWidth = this.column.width;
456
     * ```
457
     *
458
     * @memberof IgxColumnComponent
459
     */
460
    @notifyChanges(true)
461
    @WatchColumnChanges()
462
    @Input()
463
    public get width(): string {
464
        const isAutoWidth = this._width && typeof this._width === 'string' && this._width === 'auto';
2,131,650✔
465
        if (isAutoWidth) {
2,131,650✔
466
            if (!this.autoSize) {
21,290✔
467
                return 'fit-content';
11,774✔
468
            } else {
469
                return this.autoSize + 'px';
9,516✔
470
            }
471

472
        }
473
        return this.widthSetByUser ? this._width : this.defaultWidth;
2,110,360✔
474
    }
475

476
    /**
477
     * Sets the `width` of the column.
478
     * ```html
479
     * <igx-column [width] = "'25%'"></igx-column>
480
     * ```
481
     *
482
     * Two-way data binding.
483
     * ```html
484
     * <igx-column [(width)]="model.columns[0].width"></igx-column>
485
     * ```
486
     *
487
     * @memberof IgxColumnComponent
488
     */
489
    public set width(value: string) {
490
        if (value) {
15,315✔
491
            this._calcWidth = null;
13,392✔
492
            this.calcPixelWidth = NaN;
13,392✔
493
            this.widthSetByUser = true;
13,392✔
494
            // width could be passed as number from the template
495
            // host bindings are not px affixed so we need to ensure we affix simple number strings
496
            if (typeof (value) === 'number' || value.match(/^[0-9]*$/)) {
13,392✔
497
                value = value + 'px';
877✔
498
            }
499
            if (value === 'fit-content') {
13,392✔
500
                value = 'auto';
1✔
501
            }
502
            this._width = value;
13,392✔
503
            if (this.grid) {
13,392✔
504
                this.cacheCalcWidth();
13,392✔
505
            }
506
            this.widthChange.emit(this._width);
13,392✔
507
        }
508
    }
509

510
    /** @hidden @internal **/
511
    public autoSize: number;
512

513
    /**
514
     * Sets/gets the maximum `width` of the column.
515
     * ```typescript
516
     * let columnMaxWidth = this.column.width;
517
     * ```
518
     * ```html
519
     * <igx-column [maxWidth] = "'150px'"></igx-column>
520
     * ```
521
     *
522
     * @memberof IgxColumnComponent
523
     */
524
    @WatchColumnChanges()
525
    @Input()
526
    public maxWidth: string;
527

528
    /**
529
     * Sets/gets the class selector of the column header.
530
     * ```typescript
531
     * let columnHeaderClass = this.column.headerClasses;
532
     * ```
533
     * ```html
534
     * <igx-column [headerClasses] = "'column-header'"></igx-column>
535
     * ```
536
     *
537
     * @memberof IgxColumnComponent
538
     */
539
    @notifyChanges()
540
    @WatchColumnChanges()
541
    @Input()
542
    public headerClasses = '';
29,102✔
543

544
    /**
545
     * Sets conditional style properties on the column header.
546
     * Similar to `ngStyle` it accepts an object literal where the keys are
547
     * the style properties and the value is the expression to be evaluated.
548
     * ```typescript
549
     * styles = {
550
     *  background: 'royalblue',
551
     *  color: (column) => column.pinned ? 'red': 'inherit'
552
     * }
553
     * ```
554
     * ```html
555
     * <igx-column [headerStyles]="styles"></igx-column>
556
     * ```
557
     *
558
     * @memberof IgxColumnComponent
559
     */
560
    @notifyChanges()
561
    @WatchColumnChanges()
562
    @Input()
563
    public headerStyles = null;
29,102✔
564

565
    /**
566
     * Sets/gets the class selector of the column group header.
567
     * ```typescript
568
     * let columnHeaderClass = this.column.headerGroupClasses;
569
     * ```
570
     * ```html
571
     * <igx-column [headerGroupClasses] = "'column-group-header'"></igx-column>
572
     * ```
573
     *
574
     * @memberof IgxColumnComponent
575
     */
576
    @notifyChanges()
577
    @WatchColumnChanges()
578
    @Input()
579
    public headerGroupClasses = '';
29,102✔
580

581
    /**
582
     * Sets conditional style properties on the column header group wrapper.
583
     * Similar to `ngStyle` it accepts an object literal where the keys are
584
     * the style properties and the value is the expression to be evaluated.
585
     * ```typescript
586
     * styles = {
587
     *  background: 'royalblue',
588
     *  color: (column) => column.pinned ? 'red': 'inherit'
589
     * }
590
     * ```
591
     * ```html
592
     * <igx-column [headerGroupStyles]="styles"></igx-column>
593
     * ```
594
     *
595
     * @memberof IgxColumnComponent
596
     */
597
    @notifyChanges()
598
    @WatchColumnChanges()
599
    @Input()
600
    public headerGroupStyles = null;
29,102✔
601

602
    /* treatAsRef */
603
    /**
604
     * Sets a conditional class selector of the column cells.
605
     * Accepts an object literal, containing key-value pairs,
606
     * where the key is the name of the CSS class, while the
607
     * value is either a callback function that returns a boolean,
608
     * or boolean, like so:
609
     * ```typescript
610
     * callback = (rowData, columnKey, cellValue, rowIndex) => { return rowData[columnKey] > 6; }
611
     * cellClasses = { 'className' : this.callback };
612
     * ```
613
     * ```html
614
     * <igx-column [cellClasses] = "cellClasses"></igx-column>
615
     * <igx-column [cellClasses] = "{'class1' : true }"></igx-column>
616
     * ```
617
     *
618
     * @memberof IgxColumnComponent
619
     */
620
    @notifyChanges()
621
    @WatchColumnChanges()
622
    @Input()
623
    public cellClasses: any;
624

625
    /* treatAsRef */
626
    /**
627
     * Sets conditional style properties on the column cells.
628
     * Similar to `ngStyle` it accepts an object literal where the keys are
629
     * the style properties and the value is the expression to be evaluated.
630
     * As with `cellClasses` it accepts a callback function.
631
     * ```typescript
632
     * styles = {
633
     *  background: 'royalblue',
634
     *  color: (rowData, columnKey, cellValue, rowIndex) => value.startsWith('Important') ? 'red': 'inherit'
635
     * }
636
     * ```
637
     * ```html
638
     * <igx-column [cellStyles]="styles"></igx-column>
639
     * ```
640
     *
641
     * @memberof IgxColumnComponent
642
     */
643
    @notifyChanges()
644
    @WatchColumnChanges()
645
    @Input()
646
    public cellStyles = null;
29,102✔
647

648
    /* blazorAlternateType: CellValueFormatterEventHandler */
649
    /* blazorOnlyScript */
650
    /**
651
     * Applies display format to cell values in the column. Does not modify the underlying data.
652
     *
653
     * @remarks
654
     * Note: As the formatter is used in places like the Excel style filtering dialog, in certain
655
     * scenarios (remote filtering for example), the row data argument can be `undefined`.
656
     *
657
     *
658
     * In this example, we check to see if the column name is Salary, and then provide a method as the column formatter
659
     * to format the value into a currency string.
660
     *
661
     * @example
662
     * ```typescript
663
     * columnInit(column: IgxColumnComponent) {
664
     *   if (column.field == "Salary") {
665
     *     column.formatter = (salary => this.format(salary));
666
     *   }
667
     * }
668
     *
669
     * format(value: number) : string {
670
     *   return formatCurrency(value, "en-us", "$");
671
     * }
672
     * ```
673
     *
674
     * @example
675
     * ```typescript
676
     * const column = this.grid.getColumnByName('Address');
677
     * const addressFormatter = (address: string, rowData: any) => data.privacyEnabled ? 'unknown' : address;
678
     * column.formatter = addressFormatter;
679
     * ```
680
     *
681
     * @memberof IgxColumnComponent
682
     */
683
    @notifyChanges()
684
    @WatchColumnChanges()
685
    @Input()
686
    public formatter: (value: any, rowData?: any) => any;
687

688
    /* blazorAlternateType: SummaryValueFormatterEventHandler */
689
    /* blazorOnlyScript */
690
    /* forceCastDelegate */
691
    /**
692
     * The summaryFormatter is used to format the display of the column summaries.
693
     *
694
     * In this example, we check to see if the column name is OrderDate, and then provide a method as the summaryFormatter
695
     * to change the locale for the dates to 'fr-FR'. The summaries with the count key are skipped so they are displayed as numbers.
696
     *
697
     * ```typescript
698
     * columnInit(column: IgxColumnComponent) {
699
     *   if (column.field == "OrderDate") {
700
     *     column.summaryFormatter = this.summaryFormat;
701
     *   }
702
     * }
703
     *
704
     * summaryFormat(summary: IgxSummaryResult, summaryOperand: IgxSummaryOperand): string {
705
     *   const result = summary.summaryResult;
706
     *   if(summaryResult.key !== 'count' && result !== null && result !== undefined) {
707
     *      const pipe = new DatePipe('fr-FR');
708
     *      return pipe.transform(result,'mediumDate');
709
     *   }
710
     *   return result;
711
     * }
712
     * ```
713
     *
714
     * @memberof IgxColumnComponent
715
     */
716
    @notifyChanges()
717
    @WatchColumnChanges()
718
    @Input()
719
    public summaryFormatter: (summary: IgxSummaryResult, summaryOperand: IgxSummaryOperand) => any;
720

721
    /**
722
     * Sets/gets whether the column filtering should be case sensitive.
723
     * Default value is `true`.
724
     * ```typescript
725
     * let filteringIgnoreCase = this.column.filteringIgnoreCase;
726
     * ```
727
     * ```html
728
     * <igx-column [filteringIgnoreCase] = "false"></igx-column>
729
     * ```
730
     *
731
     * @memberof IgxColumnComponent
732
     */
733
    @WatchColumnChanges()
734
    @Input({ transform: booleanAttribute })
735
    public filteringIgnoreCase = true;
29,102✔
736
    /**
737
     * Sets/gets whether the column sorting should be case sensitive.
738
     * Default value is `true`.
739
     * ```typescript
740
     * let sortingIgnoreCase = this.column.sortingIgnoreCase;
741
     * ```
742
     * ```html
743
     * <igx-column [sortingIgnoreCase] = "false"></igx-column>
744
     * ```
745
     *
746
     * @memberof IgxColumnComponent
747
     */
748
    @WatchColumnChanges()
749
    @Input({ transform: booleanAttribute })
750
    public sortingIgnoreCase = true;
29,102✔
751
    /**
752
     * Sets/gets whether the column is `searchable`.
753
     * Default value is `true`.
754
     * ```typescript
755
     * let isSearchable =  this.column.searchable';
756
     * ```
757
     * ```html
758
     *  <igx-column [searchable] = "false"></igx-column>
759
     * ```
760
     *
761
     * @memberof IgxColumnComponent
762
     */
763
    @notifyChanges()
764
    @WatchColumnChanges()
765
    @Input({ transform: booleanAttribute })
766
    public searchable = true;
29,102✔
767
    /**
768
     * Sets/gets the data type of the column values.
769
     * Default value is `string`.
770
     * ```typescript
771
     * let columnDataType = this.column.dataType;
772
     * ```
773
     * ```html
774
     * <igx-column [dataType] = "'number'"></igx-column>
775
     * ```
776
     *
777
     * @memberof IgxColumnComponent
778
     */
779
    @Input()
780
    public dataType: GridColumnDataType = GridColumnDataType.String;
29,102✔
781

782
    /** @hidden */
783
    @Input()
784
    public collapsibleIndicatorTemplate: TemplateRef<IgxColumnTemplateContext>;
785

786
    /**
787
     * Row index where the current field should end.
788
     * The amount of rows between rowStart and rowEnd will determine the amount of spanning rows to that field
789
     * ```html
790
     * <igx-column-layout>
791
     *   <igx-column [rowEnd]="2" [rowStart]="1" [colStart]="1"></igx-column>
792
     * </igx-column-layout>
793
     * ```
794
     *
795
     * @memberof IgxColumnComponent
796
     */
797
    @Input()
798
    public rowEnd: number;
799

800
    /**
801
     * Column index where the current field should end.
802
     * The amount of columns between colStart and colEnd will determine the amount of spanning columns to that field
803
     * ```html
804
     * <igx-column-layout>
805
     *   <igx-column [colEnd]="3" [rowStart]="1" [colStart]="1"></igx-column>
806
     * </igx-column-layout>
807
     * ```
808
     *
809
     * @memberof IgxColumnComponent
810
     */
811
    @Input()
812
    public colEnd: number;
813

814
    /**
815
     * Row index from which the field is starting.
816
     * ```html
817
     * <igx-column-layout>
818
     *   <igx-column [rowStart]="1" [colStart]="1"></igx-column>
819
     * </igx-column-layout>
820
     * ```
821
     *
822
     * @memberof IgxColumnComponent
823
     */
824
    @Input()
825
    public rowStart: number;
826

827
    /**
828
     * Column index from which the field is starting.
829
     * ```html
830
     * <igx-column-layout>
831
     *   <igx-column [colStart]="1" [rowStart]="1"></igx-column>
832
     * </igx-column-layout>
833
     * ```
834
     *
835
     * @memberof IgxColumnComponent
836
     */
837
    @Input()
838
    public colStart: number;
839

840
    /**
841
     * Sets/gets custom properties provided in additional template context.
842
     *
843
     * ```html
844
     * <igx-column [additionalTemplateContext]="contextObject">
845
     *   <ng-template igxCell let-cell="cell" let-props="additionalTemplateContext">
846
     *      {{ props }}
847
     *   </ng-template>
848
     * </igx-column>
849
     * ```
850
     *
851
     * @memberof IgxColumnComponent
852
     */
853
    @Input()
854
    public additionalTemplateContext: any;
855

856
    /**
857
     * @hidden
858
     */
859
    @Output()
860
    public widthChange = new EventEmitter<string>();
29,102✔
861

862
    /**
863
     * @hidden
864
     */
865
    @Output()
866
    public pinnedChange = new EventEmitter<boolean>();
29,102✔
867
    /**
868
     * @hidden
869
     */
870
    @ContentChild(IgxFilterCellTemplateDirective, { read: IgxFilterCellTemplateDirective })
871
    public filterCellTemplateDirective: IgxFilterCellTemplateDirective;
872
    /**
873
     * @hidden
874
     */
875
    @ContentChild(IgxSummaryTemplateDirective, { read: IgxSummaryTemplateDirective })
876
    protected summaryTemplateDirective: IgxSummaryTemplateDirective;
877
    /**
878
     * @hidden
879
     * @see {@link bodyTemplate}
880
     */
881
    @ContentChild(IgxCellTemplateDirective, { read: IgxCellTemplateDirective })
882
    protected cellTemplate: IgxCellTemplateDirective;
883
    /**
884
     * @hidden
885
     */
886
    @ContentChild(IgxCellValidationErrorDirective, { read: IgxCellValidationErrorDirective })
887
    protected cellValidationErrorTemplate: IgxCellValidationErrorDirective;
888
    /**
889
     * @hidden
890
     */
891
    @ContentChildren(IgxCellHeaderTemplateDirective, { read: IgxCellHeaderTemplateDirective, descendants: false })
892
    protected headTemplate: QueryList<IgxCellHeaderTemplateDirective>;
893
    /**
894
     * @hidden
895
     */
896
    @ContentChild(IgxCellEditorTemplateDirective, { read: IgxCellEditorTemplateDirective })
897
    protected editorTemplate: IgxCellEditorTemplateDirective;
898
    /**
899
     * @hidden
900
     */
901
    @ContentChild(IgxCollapsibleIndicatorTemplateDirective, { read: IgxCollapsibleIndicatorTemplateDirective, static: false })
902
    protected collapseIndicatorTemplate: IgxCollapsibleIndicatorTemplateDirective;
903
    /**
904
     * @hidden
905
     */
906
    public get calcWidth(): any {
907
        return this.getCalcWidth();
237,379✔
908
    }
909

910
    /** @hidden @internal **/
911
    public calcPixelWidth: number;
912

913
    /**
914
     * @hidden
915
     */
916
    public get maxWidthPx() {
917
        const gridAvailableSize = this.grid.calcWidth;
70,416✔
918
        const isPercentageWidth = this.maxWidth && typeof this.maxWidth === 'string' && this.maxWidth.indexOf('%') !== -1;
70,416✔
919
        return isPercentageWidth ? parseFloat(this.maxWidth) / 100 * gridAvailableSize : parseFloat(this.maxWidth);
70,416✔
920
    }
921

922
    /**
923
     * @hidden
924
     */
925
    public get maxWidthPercent() {
926
        const gridAvailableSize = this.grid.calcWidth;
17✔
927
        const isPercentageWidth = this.maxWidth && typeof this.maxWidth === 'string' && this.maxWidth.indexOf('%') !== -1;
17✔
928
        return isPercentageWidth ? parseFloat(this.maxWidth) : parseFloat(this.maxWidth) / gridAvailableSize * 100;
17✔
929
    }
930

931
    /**
932
     * @hidden
933
     */
934
    public get minWidthPx() {
935
        const gridAvailableSize = this.grid.calcWidth;
70,526✔
936
        const isPercentageWidth = this.minWidth && typeof this.minWidth === 'string' && this.minWidth.indexOf('%') !== -1;
70,526✔
937
        return isPercentageWidth ? parseFloat(this.minWidth) / 100 * gridAvailableSize : parseFloat(this.minWidth);
70,526✔
938
    }
939

940
    /**
941
     * @hidden
942
     */
943
    public get minWidthPercent() {
944
        const gridAvailableSize = this.grid.calcWidth;
17✔
945
        const isPercentageWidth = this.minWidth && typeof this.minWidth === 'string' && this.minWidth.indexOf('%') !== -1;
17✔
946
        return isPercentageWidth ? parseFloat(this.minWidth) : parseFloat(this.minWidth) / gridAvailableSize * 100;
17✔
947
    }
948

949

950
    /**
951
     * Sets/gets the minimum `width` of the column.
952
     * Default value is `88`;
953
     * ```typescript
954
     * let columnMinWidth = this.column.minWidth;
955
     * ```
956
     * ```html
957
     * <igx-column [minWidth] = "'100px'"></igx-column>
958
     * ```
959
     *
960
     * @memberof IgxColumnComponent
961
     */
962
    @notifyChanges()
963
    @WatchColumnChanges()
964
    @Input()
965
    public set minWidth(value: string) {
966
        const minVal = parseFloat(value);
1,475✔
967
        if (Number.isNaN(minVal)) {
1,475✔
968
            return;
45✔
969
        }
970
        this._defaultMinWidth = value;
1,430✔
971

972
    }
973
    public get minWidth(): string {
974
        return !this._defaultMinWidth ? this.defaultMinWidth : this._defaultMinWidth;
286,412✔
975
    }
976

977
    /** @hidden @internal **/
978
    public get resolvedWidth(): string {
979
        if (this.columnLayoutChild) {
4,093,988!
980
            return '';
×
981
        }
982
        const isAutoWidth = this._width && typeof this._width === 'string' && this._width === 'auto';
4,093,988✔
983
        return isAutoWidth ? this.width : this.calcPixelWidth + 'px';
4,093,988✔
984
    }
985

986
    /**
987
     * Gets the column index.
988
     * ```typescript
989
     * let columnIndex = this.column.index;
990
     * ```
991
     *
992
     * @memberof IgxColumnComponent
993
     */
994
    public get index(): number {
995
        return (this.grid as any)._columns.indexOf(this);
240,090✔
996
    }
997

998
    /**
999
     * Gets whether the column is `pinned`.
1000
     * ```typescript
1001
     * let isPinned = this.column.pinned;
1002
     * ```
1003
     *
1004
     * @memberof IgxColumnComponent
1005
     */
1006
    @WatchColumnChanges()
1007
    @Input({ transform: booleanAttribute })
1008
    public get pinned(): boolean {
1009
        return this._pinned;
2,256,709✔
1010
    }
1011
    /**
1012
     * Sets whether the column is pinned.
1013
     * Default value is `false`.
1014
     * ```html
1015
     * <igx-column [pinned] = "true"></igx-column>
1016
     * ```
1017
     *
1018
     * Two-way data binding.
1019
     * ```html
1020
     * <igx-column [(pinned)] = "model.columns[0].isPinned"></igx-column>
1021
     * ```
1022
     *
1023
     * @memberof IgxColumnComponent
1024
     */
1025
    public set pinned(value: boolean) {
1026
        if (this._pinned !== value) {
2,818✔
1027
            const isAutoWidth = this.width && typeof this.width === 'string' && this.width === 'fit-content';
564✔
1028
            if (this.grid && this.width && (isAutoWidth || !isNaN(parseInt(this.width, 10)))) {
564✔
1029
                if (value) {
392✔
1030
                    this.pin();
354✔
1031
                } else {
1032
                    this.unpin();
38✔
1033
                }
1034
                return;
392✔
1035
            }
1036
            /* No grid/width available at initialization. `initPinning` in the grid
1037
               will re-init the group (if present)
1038
            */
1039
            this._pinned = value;
172✔
1040
            this.pinnedChange.emit(this._pinned);
172✔
1041
        }
1042
    }
1043

1044
    /* treatAsRef */
1045
    /**
1046
     * Gets the column `summaries`.
1047
     * ```typescript
1048
     * let columnSummaries = this.column.summaries;
1049
     * ```
1050
     *
1051
     * @memberof IgxColumnComponent
1052
     */
1053
    @notifyChanges(true)
1054
    @WatchColumnChanges()
1055
    @Input()
1056
    public get summaries(): any {
1057
        return this._summaries;
64,443✔
1058
    }
1059

1060
    /* treatAsRef */
1061
    /**
1062
     * Sets the column `summaries`.
1063
     * ```typescript
1064
     * this.column.summaries = IgxNumberSummaryOperand;
1065
     * ```
1066
     *
1067
     * @memberof IgxColumnComponent
1068
     */
1069
    public set summaries(classRef: any) {
1070
        if (isConstructor(classRef)) {
24,064✔
1071
            this._summaries = new classRef();
24,058✔
1072
        }
1073

1074
        if (this.grid) {
24,064✔
1075
            this.grid.summaryService.removeSummariesCachePerColumn(this.field);
24,064✔
1076
            this.grid.summaryPipeTrigger++;
24,064✔
1077
            this.grid.summaryService.resetSummaryHeight();
24,064✔
1078
        }
1079
    }
1080

1081
    /**
1082
     * Sets/gets the summary operands to exclude from display.
1083
     * Accepts an array of string keys representing the summary types to disable, such as 'Min', 'Max', 'Count' etc.
1084
     * ```typescript
1085
     * let disabledSummaries = this.column.disabledSummaries;
1086
     * ```
1087
     * ```html
1088
     * <igx-column [disabledSummaries]="['min', 'max', 'average']"></igx-column>
1089
     * ```
1090
     *
1091
     * @memberof IgxColumnComponent
1092
     */
1093
    @Input()
1094
    public get disabledSummaries(): string[] {
1095
        return this._disabledSummaries;
16,538✔
1096
    }
1097

1098
    public set disabledSummaries(value: string[]) {
1099
        this._disabledSummaries = value;
1,413✔
1100
        if (this.grid) {
1,413✔
1101
            this.grid.summaryService.removeSummariesCachePerColumn(this.field);
1,413✔
1102
            this.grid.summaryPipeTrigger++;
1,413✔
1103
            this.grid.summaryService.resetSummaryHeight();
1,413✔
1104
        }
1105
    }
1106

1107
    /**
1108
     * Gets the column `filters`.
1109
     * ```typescript
1110
     * let columnFilters = this.column.filters'
1111
     * ```
1112
     *
1113
     * @memberof IgxColumnComponent
1114
     */
1115
    @Input()
1116
    public get filters(): IgxFilteringOperand {
1117
        return this._filters;
74,479✔
1118
    }
1119
    /**
1120
     * Sets the column `filters`.
1121
     * ```typescript
1122
     * this.column.filters = IgxBooleanFilteringOperand.instance().
1123
     * ```
1124
     *
1125
     * @memberof IgxColumnComponent
1126
     */
1127
    public set filters(instance: IgxFilteringOperand) {
1128
        this._filters = instance;
24,050✔
1129
    }
1130
    /**
1131
     * Gets the column `sortStrategy`.
1132
     * ```typescript
1133
     * let sortStrategy = this.column.sortStrategy
1134
     * ```
1135
     *
1136
     * @memberof IgxColumnComponent
1137
     */
1138
    @Input()
1139
    public get sortStrategy(): ISortingStrategy {
1140
        return this._sortStrategy;
2,842✔
1141
    }
1142
    /**
1143
     * Sets the column `sortStrategy`.
1144
     * ```typescript
1145
     * this.column.sortStrategy = new CustomSortingStrategy().
1146
     * class CustomSortingStrategy extends SortingStrategy {...}
1147
     * ```
1148
     *
1149
     * @memberof IgxColumnComponent
1150
     */
1151
    public set sortStrategy(classRef: ISortingStrategy) {
1152
        this._sortStrategy = classRef;
1,409✔
1153
    }
1154

1155
    /* blazorSuppress */
1156
    /**
1157
     * Gets the function that compares values for grouping.
1158
     * ```typescript
1159
     * let groupingComparer = this.column.groupingComparer'
1160
     * ```
1161
     *
1162
     * @memberof IgxColumnComponent
1163
     */
1164
    @Input()
1165
    public get groupingComparer(): (a: any, b: any, currRec?: any, groupRec?: any) => number {
1166
        return this._groupingComparer;
3,273✔
1167
    }
1168

1169
    /* blazorSuppress */
1170
    /**
1171
     * Sets a custom function to compare values for grouping.
1172
     * Subsequent values in the sorted data that the function returns 0 for are grouped.
1173
     * ```typescript
1174
     * this.column.groupingComparer = (a: any, b: any, currRec?: any, groupRec?: any) => { return a === b ? 0 : -1; }
1175
     * ```
1176
     *
1177
     * @memberof IgxColumnComponent
1178
     */
1179
    public set groupingComparer(funcRef: (a: any, b: any, currRec?: any, groupRec?: any) => number) {
1180
        this._groupingComparer = funcRef;
1,409✔
1181
    }
1182
    /**
1183
     * @hidden @internal
1184
     */
1185
    public get defaultMinWidth(): string {
1186
        if (!this.grid) {
265,672!
1187
            return '80';
×
1188
        }
1189
        switch (this.grid.gridSize) {
265,672✔
1190
            case Size.Medium:
1191
                return '64';
12,321✔
1192
            case Size.Small:
1193
                return '56';
1,173✔
1194
            default:
1195
                return '80';
252,178✔
1196
        }
1197
    }
1198
    /**
1199
     * Returns a reference to the `summaryTemplate`.
1200
     * ```typescript
1201
     * let summaryTemplate = this.column.summaryTemplate;
1202
     * ```
1203
     *
1204
     * @memberof IgxColumnComponent
1205
     */
1206
    @notifyChanges()
1207
    @WatchColumnChanges()
1208
    @Input()
1209
    public get summaryTemplate(): TemplateRef<IgxSummaryTemplateContext> {
1210
        return this._summaryTemplate;
79,614✔
1211
    }
1212
    /**
1213
     * Sets the summary template.
1214
     * ```html
1215
     * <ng-template #summaryTemplate igxSummary let-summaryResults>
1216
     *    <p>{{ summaryResults[0].label }}: {{ summaryResults[0].summaryResult }}</p>
1217
     *    <p>{{ summaryResults[1].label }}: {{ summaryResults[1].summaryResult }}</p>
1218
     * </ng-template>
1219
     * ```
1220
     * ```typescript
1221
     * @ViewChild("'summaryTemplate'", {read: TemplateRef })
1222
     * public summaryTemplate: TemplateRef<any>;
1223
     * this.column.summaryTemplate = this.summaryTemplate;
1224
     * ```
1225
     *
1226
     * @memberof IgxColumnComponent
1227
     */
1228
    public set summaryTemplate(template: TemplateRef<IgxSummaryTemplateContext>) {
1229
        this._summaryTemplate = template;
1,412✔
1230
    }
1231

1232
    /**
1233
     * Returns a reference to the `bodyTemplate`.
1234
     * ```typescript
1235
     * let bodyTemplate = this.column.bodyTemplate;
1236
     * ```
1237
     *
1238
     * @memberof IgxColumnComponent
1239
     */
1240
    @notifyChanges()
1241
    @WatchColumnChanges()
1242
    @Input('cellTemplate')
1243
    public get bodyTemplate(): TemplateRef<IgxCellTemplateContext> {
1244
        return this._bodyTemplate;
1,200,546✔
1245
    }
1246
    /**
1247
     * Sets the body template.
1248
     * ```html
1249
     * <ng-template #bodyTemplate igxCell let-val>
1250
     *    <div style = "background-color: yellowgreen" (click) = "changeColor(val)">
1251
     *       <span> {{val}} </span>
1252
     *    </div>
1253
     * </ng-template>
1254
     * ```
1255
     * ```typescript
1256
     * @ViewChild("'bodyTemplate'", {read: TemplateRef })
1257
     * public bodyTemplate: TemplateRef<any>;
1258
     * this.column.bodyTemplate = this.bodyTemplate;
1259
     * ```
1260
     *
1261
     * @memberof IgxColumnComponent
1262
     */
1263
    public set bodyTemplate(template: TemplateRef<IgxCellTemplateContext>) {
1264
        this._bodyTemplate = template;
1,376✔
1265
    }
1266
    /**
1267
     * Returns a reference to the header template.
1268
     * ```typescript
1269
     * let headerTemplate = this.column.headerTemplate;
1270
     * ```
1271
     *
1272
     * @memberof IgxColumnComponent
1273
     */
1274
    @notifyChanges()
1275
    @WatchColumnChanges()
1276
    @Input()
1277
    public get headerTemplate(): TemplateRef<IgxColumnTemplateContext> {
1278
        return this._headerTemplate;
259,416✔
1279
    }
1280
    /**
1281
     * Sets the header template.
1282
     * Note that the column header height is fixed and any content bigger than it will be cut off.
1283
     * ```html
1284
     * <ng-template #headerTemplate>
1285
     *   <div style = "background-color:black" (click) = "changeColor(val)">
1286
     *       <span style="color:red" >{{column.field}}</span>
1287
     *   </div>
1288
     * </ng-template>
1289
     * ```
1290
     * ```typescript
1291
     * @ViewChild("'headerTemplate'", {read: TemplateRef })
1292
     * public headerTemplate: TemplateRef<any>;
1293
     * this.column.headerTemplate = this.headerTemplate;
1294
     * ```
1295
     *
1296
     * @memberof IgxColumnComponent
1297
     */
1298
    public set headerTemplate(template: TemplateRef<IgxColumnTemplateContext>) {
1299
        this._headerTemplate = template;
5,122✔
1300
    }
1301
    /**
1302
     * Returns a reference to the inline editor template.
1303
     * ```typescript
1304
     * let inlineEditorTemplate = this.column.inlineEditorTemplate;
1305
     * ```
1306
     *
1307
     * @memberof IgxColumnComponent
1308
     */
1309
    @notifyChanges()
1310
    @WatchColumnChanges()
1311
    @Input('cellEditorTemplate')
1312
    public get inlineEditorTemplate(): TemplateRef<IgxCellTemplateContext> {
1313
        return this._inlineEditorTemplate;
5,462✔
1314
    }
1315
    /**
1316
     * Sets the inline editor template.
1317
     * ```html
1318
     * <ng-template #inlineEditorTemplate igxCellEditor let-cell="cell">
1319
     *     <input type="string" [(ngModel)]="cell.value"/>
1320
     * </ng-template>
1321
     * ```
1322
     * ```typescript
1323
     * @ViewChild("'inlineEditorTemplate'", {read: TemplateRef })
1324
     * public inlineEditorTemplate: TemplateRef<any>;
1325
     * this.column.inlineEditorTemplate = this.inlineEditorTemplate;
1326
     * ```
1327
     *
1328
     * @memberof IgxColumnComponent
1329
     */
1330
    public set inlineEditorTemplate(template: TemplateRef<IgxCellTemplateContext>) {
1331
        this._inlineEditorTemplate = template;
1,373✔
1332
    }
1333

1334
    /**
1335
     * Returns a reference to the validation error template.
1336
     * ```typescript
1337
     * let errorTemplate = this.column.errorTemplate;
1338
     * ```
1339
     */
1340
    @notifyChanges()
1341
    @WatchColumnChanges()
1342
    @Input('errorTemplate')
1343
    public get errorTemplate(): TemplateRef<IgxCellTemplateContext> {
1344
        return this._errorTemplate;
1,145,103✔
1345
    }
1346
    /**
1347
     * Sets the error template.
1348
     * ```html
1349
     * <ng-template igxCellValidationError let-cell="cell" #errorTemplate >
1350
     *     <div *ngIf="cell.validation.errors?.['forbiddenName']">
1351
     *      This name is forbidden.
1352
     *     </div>
1353
     * </ng-template>
1354
     * ```
1355
     * ```typescript
1356
     * @ViewChild("'errorTemplate'", {read: TemplateRef })
1357
     * public errorTemplate: TemplateRef<any>;
1358
     * this.column.errorTemplate = this.errorTemplate;
1359
     * ```
1360
     */
1361
    public set errorTemplate(template: TemplateRef<IgxCellTemplateContext>) {
1362
        this._errorTemplate = template;
1,406✔
1363
    }
1364

1365
    /**
1366
     * Returns a reference to the `filterCellTemplate`.
1367
     * ```typescript
1368
     * let filterCellTemplate = this.column.filterCellTemplate;
1369
     * ```
1370
     *
1371
     * @memberof IgxColumnComponent
1372
     */
1373
    @notifyChanges()
1374
    @WatchColumnChanges()
1375
    @Input('filterCellTemplate')
1376
    public get filterCellTemplate(): TemplateRef<IgxColumnTemplateContext> {
1377
        return this._filterCellTemplate;
41,639✔
1378
    }
1379
    /**
1380
     * Sets the quick filter template.
1381
     * ```html
1382
     * <ng-template #filterCellTemplate IgxFilterCellTemplate let-column="column">
1383
     *    <input (input)="onInput()">
1384
     * </ng-template>
1385
     * ```
1386
     * ```typescript
1387
     * @ViewChild("'filterCellTemplate'", {read: TemplateRef })
1388
     * public filterCellTemplate: TemplateRef<any>;
1389
     * this.column.filterCellTemplate = this.filterCellTemplate;
1390
     * ```
1391
     *
1392
     * @memberof IgxColumnComponent
1393
     */
1394
    public set filterCellTemplate(template: TemplateRef<IgxColumnTemplateContext>) {
1395
        this._filterCellTemplate = template;
1,422✔
1396
    }
1397

1398
    /**
1399
     * @hidden @internal
1400
     */
1401
    public get cells(): CellType[] {
1402
        return this.grid.dataView
23✔
1403
            .map((rec, index) => {
1404
                if (!this.grid.isGroupByRecord(rec) && !this.grid.isSummaryRow(rec)) {
1,273✔
1405
                    this.grid.pagingMode === 1 && this.grid.page !== 0 ? index = index + this.grid.perPage * this.grid.page : index = this.grid.dataRowList.first.index + index;
1,273!
1406
                    const cell = new IgxGridCell(this.grid as any, index, this);
1,273✔
1407
                    return cell;
1,273✔
1408
                }
1409
            }).filter(cell => cell);
1,273✔
1410
    }
1411

1412

1413
    /**
1414
     * @hidden @internal
1415
     */
1416
    public get _cells(): CellType[] {
1417
        return this.grid.rowList.filter((row) => row instanceof IgxRowDirective)
2,865✔
1418
            .map((row) => {
1419
                if (row._cells) {
2,865✔
1420
                    return row._cells.filter((cell) => cell.columnIndex === this.index);
17,213✔
1421
                }
1422
            }).reduce((a, b) => a.concat(b), []);
2,865✔
1423
    }
1424

1425
    /**
1426
     * Gets the column visible index.
1427
     * If the column is not visible, returns `-1`.
1428
     * ```typescript
1429
     * let visibleColumnIndex =  this.column.visibleIndex;
1430
     * ```
1431
     *
1432
     * @memberof IgxColumnComponent
1433
     */
1434
    public get visibleIndex(): number {
1435
        if (!isNaN(this._vIndex)) {
5,401,543✔
1436
            return this._vIndex;
4,957,932✔
1437
        }
1438
        const unpinnedColumns = this.grid.unpinnedColumns.filter(c => !c.columnGroup);
4,385,915✔
1439
        const pinnedColumns = this.grid.pinnedColumns.filter(c => !c.columnGroup);
443,611✔
1440

1441
        let col = this;
443,611✔
1442
        let vIndex = -1;
443,611✔
1443

1444
        if (this.columnGroup) {
443,611✔
1445
            col = this.allChildren.filter(c => !c.columnGroup && !c.hidden)[0] as any;
24,347✔
1446
        }
1447
        if (this.columnLayoutChild) {
443,611✔
1448
            return this.parent.childrenVisibleIndexes.find(x => x.column === this).index;
859,727✔
1449
        }
1450

1451
        if (!this.pinned) {
111,418✔
1452
            const indexInCollection = unpinnedColumns.indexOf(col);
109,229✔
1453
            vIndex = indexInCollection === -1 ?
109,229✔
1454
                -1 :
1455
                (this.grid.isPinningToStart ?
108,613✔
1456
                    pinnedColumns.length + indexInCollection :
1457
                    indexInCollection);
1458
        } else {
1459
            const indexInCollection = pinnedColumns.indexOf(col);
2,189✔
1460
            vIndex = this.grid.isPinningToStart ?
2,189✔
1461
                indexInCollection :
1462
                unpinnedColumns.length + indexInCollection;
1463
        }
1464
        this._vIndex = vIndex;
111,418✔
1465
        return vIndex;
111,418✔
1466
    }
1467

1468
    /* blazorCSSuppress - Blazor doesn't carry over the ColumnType interface + should translate as static bool value */
1469
    /**
1470
     * Returns a boolean indicating if the column is a `ColumnGroup`.
1471
     * ```typescript
1472
     * let columnGroup =  this.column.columnGroup;
1473
     * ```
1474
     *
1475
     * @memberof IgxColumnComponent
1476
     */
1477
    public get columnGroup() {
1478
        return false;
8,041,625✔
1479
    }
1480

1481
    /* blazorCSSuppress - Blazor doesn't carry over the ColumnType interface + should translate as static bool value */
1482
    /**
1483
     * Returns a boolean indicating if the column is a `ColumnLayout` for multi-row layout.
1484
     * ```typescript
1485
     * let columnGroup =  this.column.columnGroup;
1486
     * ```
1487
     *
1488
     * @memberof IgxColumnComponent
1489
     */
1490
    public get columnLayout() {
1491
        return false;
19,410,941✔
1492
    }
1493

1494
    /**
1495
     * Returns a boolean indicating if the column is a child of a `ColumnLayout` for multi-row layout.
1496
     * ```typescript
1497
     * let columnLayoutChild =  this.column.columnLayoutChild;
1498
     * ```
1499
     *
1500
     * @memberof IgxColumnComponent
1501
     */
1502
    public get columnLayoutChild(): boolean {
1503
        return this.parent && this.parent.columnLayout;
16,887,279✔
1504
    }
1505

1506
    /**
1507
     * A list containing all the child columns under this column (if any).
1508
     * Empty without children or if this column is not Group or Layout.
1509
     */
1510
    public get childColumns(): ColumnType[] {
1511
        return [];
×
1512
    }
1513

1514
    /** @hidden @internal **/
1515
    public get allChildren(): IgxColumnComponent[] {
1516
        return [];
310✔
1517
    }
1518
    /**
1519
     * Returns the level of the column in a column group.
1520
     * Returns `0` if the column doesn't have a `parent`.
1521
     * ```typescript
1522
     * let columnLevel =  this.column.level;
1523
     * ```
1524
     *
1525
     * @memberof IgxColumnComponent
1526
     */
1527
    public get level() {
1528
        let ptr = this.parent;
471,505✔
1529
        let lvl = 0;
471,505✔
1530

1531
        while (ptr) {
471,505✔
1532
            lvl++;
144,792✔
1533
            ptr = ptr.parent;
144,792✔
1534
        }
1535
        return lvl;
471,505✔
1536
    }
1537

1538
    /** @hidden @internal **/
1539
    public get isLastPinned(): boolean {
1540
        return this.grid.isPinningToStart &&
1,089,767✔
1541
            this.grid.pinnedColumns[this.grid.pinnedColumns.length - 1] === this;
1542
    }
1543

1544
    /** @hidden @internal **/
1545
    public get isFirstPinned(): boolean {
1546
        const pinnedCols = this.grid.pinnedColumns.filter(x => !x.columnGroup);
1,005,671✔
1547
        return !this.grid.isPinningToStart && pinnedCols[0] === this;
1,005,671✔
1548
    }
1549

1550
    /** @hidden @internal **/
1551
    public get rightPinnedOffset(): string {
1552
        return this.pinned && !this.grid.isPinningToStart ?
725,116✔
1553
            - this.grid.pinnedWidth - this.grid.headerFeaturesWidth + 'px' :
1554
            null;
1555
    }
1556

1557
    /** @hidden @internal **/
1558
    public get gridRowSpan(): number {
1559
        return this.rowEnd && this.rowStart ? this.rowEnd - this.rowStart : 1;
1,274✔
1560
    }
1561
    /** @hidden @internal **/
1562
    public get gridColumnSpan(): number {
1563
        return this.colEnd && this.colStart ? this.colEnd - this.colStart : 1;
687,115✔
1564
    }
1565

1566
    /**
1567
     * Indicates whether the column will be visible when its parent is collapsed.
1568
     * ```html
1569
     * <igx-column-group>
1570
     *   <igx-column [visibleWhenCollapsed]="true"></igx-column>
1571
     * </igx-column-group>
1572
     * ```
1573
     *
1574
     * @memberof IgxColumnComponent
1575
     */
1576
    @notifyChanges(true)
1577
    @Input({ transform: booleanAttribute })
1578
    public set visibleWhenCollapsed(value: boolean) {
1579
        this._visibleWhenCollapsed = value;
1,755✔
1580
        this.visibleWhenCollapsedChange.emit(this._visibleWhenCollapsed);
1,755✔
1581
        if (this.parent) {
1,755✔
1582
            this.parent?.setExpandCollapseState?.();
26✔
1583
        }
1584
    }
1585

1586
    public get visibleWhenCollapsed(): boolean {
1587
        return this._visibleWhenCollapsed;
9,469✔
1588
    }
1589

1590
    /* mustSetInCodePlatforms: WebComponents;Blazor;React */
1591
    /**
1592
     * @remarks
1593
     * Pass optional parameters for DatePipe and/or DecimalPipe to format the display value for date and numeric columns.
1594
     * Accepts an `IColumnPipeArgs` object with any of the `format`, `timezone` and `digitsInfo` properties.
1595
     * For more details see https://angular.io/api/common/DatePipe and https://angular.io/api/common/DecimalPipe
1596
     * @example
1597
     * ```typescript
1598
     * const pipeArgs: IColumnPipeArgs = {
1599
     *      format: 'longDate',
1600
     *      timezone: 'UTC',
1601
     *      digitsInfo: '1.1-2'
1602
     * }
1603
     * ```
1604
     * ```html
1605
     * <igx-column dataType="date" [pipeArgs]="pipeArgs"></igx-column>
1606
     * <igx-column dataType="number" [pipeArgs]="pipeArgs"></igx-column>
1607
     * ```
1608
     * @memberof IgxColumnComponent
1609
     */
1610
    @notifyChanges()
1611
    @WatchColumnChanges()
1612
    @Input()
1613
    public set pipeArgs(value: IColumnPipeArgs) {
1614
        this._columnPipeArgs = Object.assign(this._columnPipeArgs, value);
1,445✔
1615
        this.grid.summaryService.clearSummaryCache();
1,445✔
1616
        this.grid.pipeTrigger++;
1,445✔
1617
    }
1618
    /* mustSetInCodePlatforms: WebComponents;Blazor */
1619
    public get pipeArgs(): IColumnPipeArgs {
1620
        return this._columnPipeArgs;
1,654,291✔
1621
    }
1622

1623
    /**
1624
     * Pass optional properties for the default column editors.
1625
     * @remarks
1626
     * Options may be applicable only to specific column type editors.
1627
     * @example
1628
     * ```typescript
1629
     * const editorOptions: IColumnEditorOptions = {
1630
     *      dateTimeFormat: 'MM/dd/YYYY',
1631
     * }
1632
     * ```
1633
     * ```html
1634
     * <igx-column dataType="date" [editorOptions]="editorOptions"></igx-column>
1635
     * ```
1636
     * @memberof IgxColumnComponent
1637
     */
1638
    @notifyChanges()
1639
    @WatchColumnChanges()
1640
    @Input()
1641
    public set editorOptions(value: IColumnEditorOptions) {
1642
        this._editorOptions = value;
1,416✔
1643
    }
1644
    public get editorOptions(): IColumnEditorOptions {
1645
        return this._editorOptions;
4,556✔
1646
    }
1647

1648
    /**
1649
     * @hidden
1650
     * @internal
1651
     */
1652
    public get collapsible() {
1653
        return false;
×
1654
    }
1655
    public set collapsible(_value: boolean) { }
1656

1657
    /**
1658
     * @hidden
1659
     * @internal
1660
     */
1661
    public get expanded() {
1662
        return true;
×
1663
    }
1664
    public set expanded(_value: boolean) { }
1665

1666
    /**
1667
     * @hidden
1668
     */
1669
    public defaultWidth: string;
1670

1671
    /**
1672
     * @hidden
1673
     */
1674
    public widthSetByUser: boolean;
1675

1676
    /**
1677
     * @hidden
1678
     */
1679
    public hasNestedPath: boolean;
1680

1681
    /**
1682
     * @hidden
1683
     * @internal
1684
     */
1685
    public defaultTimeFormat = 'hh:mm:ss a';
29,102✔
1686

1687
    /**
1688
     * @hidden
1689
     * @internal
1690
     */
1691
    public defaultDateTimeFormat = 'dd/MM/yyyy HH:mm:ss a';
29,102✔
1692

1693

1694
    /**
1695
     * Returns the filteringExpressionsTree of the column.
1696
     * ```typescript
1697
     * let tree =  this.column.filteringExpressionsTree;
1698
     * ```
1699
     *
1700
     * @memberof IgxColumnComponent
1701
     */
1702
    public get filteringExpressionsTree(): FilteringExpressionsTree {
1703
        return ExpressionsTreeUtil.find(this.grid.filteringExpressionsTree, this.field) as FilteringExpressionsTree;
63,921✔
1704
    }
1705

1706
    /* alternateName: parentColumn */
1707
    /**
1708
     * Sets/gets the parent column.
1709
     * ```typescript
1710
     * let parentColumn = this.column.parent;
1711
     * ```
1712
     * ```typescript
1713
     * this.column.parent = higherLevelColumn;
1714
     * ```
1715
     *
1716
     * @memberof IgxColumnComponent
1717
     */
1718
    public parent = null;
29,102✔
1719

1720
    /* blazorSuppress */
1721
    /**
1722
     * Sets/gets the children columns.
1723
     * ```typescript
1724
     * let columnChildren = this.column.children;
1725
     * ```
1726
     *
1727
     * @deprecated in version 18.1.0. Use the `childColumns` property instead.
1728
     */
1729
    public children: QueryList<IgxColumnComponent>;
1730
    /**
1731
     * @hidden
1732
     */
1733
    public destroy$ = new Subject<any>();
29,102✔
1734

1735
    /**
1736
     * @hidden
1737
     */
1738
    protected _applySelectableClass = false;
29,102✔
1739

1740
    protected _vIndex = NaN;
29,102✔
1741
    /**
1742
     * @hidden
1743
     */
1744
    protected _pinned = false;
29,102✔
1745
    /**
1746
     * @hidden
1747
     */
1748
    protected _bodyTemplate: TemplateRef<IgxCellTemplateContext>;
1749
    /**
1750
     * @hidden
1751
     */
1752
    protected _errorTemplate: TemplateRef<IgxCellTemplateContext>;
1753
    /**
1754
     * @hidden
1755
     */
1756
    protected _headerTemplate: TemplateRef<IgxColumnTemplateContext>;
1757
    /**
1758
     * @hidden
1759
     */
1760
    protected _summaryTemplate: TemplateRef<IgxSummaryTemplateContext>;
1761
    /**
1762
     * @hidden
1763
     */
1764
    protected _inlineEditorTemplate: TemplateRef<IgxCellTemplateContext>;
1765
    /**
1766
     * @hidden
1767
     */
1768
    protected _filterCellTemplate: TemplateRef<IgxColumnTemplateContext>;
1769
    /**
1770
     * @hidden
1771
     */
1772
    protected _summaries = null;
29,102✔
1773
    /**
1774
     * @hidden
1775
     */
1776
    private _disabledSummaries: string[] = [];
29,102✔
1777
    /**
1778
     * @hidden
1779
     */
1780
    protected _filters = null;
29,102✔
1781
    /**
1782
     * @hidden
1783
     */
1784
    protected _sortStrategy: ISortingStrategy = DefaultSortingStrategy.instance();
29,102✔
1785
    /**
1786
     * @hidden
1787
     */
1788
    protected _groupingComparer: (a: any, b: any, currRec?: any, groupRec?: any) => number;
1789
    /**
1790
     * @hidden
1791
     */
1792
    protected _hidden = false;
29,102✔
1793
    /**
1794
     * @hidden
1795
     */
1796
    protected _index: number;
1797
    /**
1798
     * @hidden
1799
     */
1800
    protected _disablePinning = false;
29,102✔
1801
    /**
1802
     * @hidden
1803
     */
1804
    protected _width: string;
1805
    /**
1806
     * @hidden
1807
     */
1808
    protected _defaultMinWidth = '';
29,102✔
1809
    /**
1810
     * @hidden
1811
     */
1812
    protected _hasSummary = false;
29,102✔
1813
    /**
1814
     * @hidden
1815
     */
1816
    protected _editable: boolean;
1817
    /**
1818
     * @hidden
1819
     */
1820
    protected _groupable = false;
29,102✔
1821
    /**
1822
     *  @hidden
1823
     */
1824
    protected _visibleWhenCollapsed;
1825
    /**
1826
     * @hidden
1827
     */
1828
    protected _collapsible = false;
29,102✔
1829
    /**
1830
     * @hidden
1831
     */
1832
    protected _expanded = true;
29,102✔
1833
    /**
1834
     * @hidden
1835
     */
1836
    protected _selectable = true;
29,102✔
1837
    /**
1838
     * @hidden
1839
     */
1840
    protected get isPrimaryColumn(): boolean {
1841
        return this.field !== undefined && this.grid !== undefined && this.field === this.grid.primaryKey;
2,402,299✔
1842
    }
1843

1844
    private _field: string;
1845
    private _calcWidth = null;
29,102✔
1846
    private _columnPipeArgs: IColumnPipeArgs = { digitsInfo: DEFAULT_DIGITS_INFO };
29,102✔
1847
    private _editorOptions: IColumnEditorOptions = { };
29,102✔
1848

1849
    constructor(
1850
        @Inject(IGX_GRID_BASE) public grid: GridType,
29,102✔
1851
        @Optional() @Self() @Inject(NG_VALIDATORS) private _validators: Validator[],
29,102✔
1852
        /** @hidden @internal **/
1853
        public cdr: ChangeDetectorRef,
29,102✔
1854
        protected platform: PlatformUtil,
29,102✔
1855
    ) {
1856
        this.validators = _validators;
29,102✔
1857
    }
1858

1859
    /**
1860
     * @hidden
1861
     * @internal
1862
     */
1863
    public resetCaches() {
1864
        this._vIndex = NaN;
284,796✔
1865
        if (this.grid) {
284,796✔
1866
            this.cacheCalcWidth();
284,796✔
1867
        }
1868
    }
1869

1870
    /**
1871
     * @hidden
1872
     */
1873
    public ngOnDestroy() {
1874
        this.destroy$.next(true);
16,135✔
1875
        this.destroy$.complete();
16,135✔
1876
    }
1877
    /**
1878
     * @hidden
1879
     */
1880
    public ngAfterContentInit(): void {
1881
        if (this.summaryTemplateDirective) {
23,963✔
1882
            this._summaryTemplate = this.summaryTemplateDirective.template;
6✔
1883
        }
1884
        if (this.cellTemplate) {
23,963✔
1885
            this._bodyTemplate = this.cellTemplate.template;
44✔
1886
        }
1887
        if (this.cellValidationErrorTemplate) {
23,963✔
1888
            this._errorTemplate = this.cellValidationErrorTemplate.template;
16✔
1889
        }
1890
        if (this.headTemplate && this.headTemplate.length) {
23,963✔
1891
            this._headerTemplate = this.headTemplate.toArray()[0].template;
81✔
1892
        }
1893
        if (this.editorTemplate) {
23,963✔
1894
            this._inlineEditorTemplate = this.editorTemplate.template;
4✔
1895
        }
1896
        if (this.filterCellTemplateDirective) {
23,963!
1897
            this._filterCellTemplate = this.filterCellTemplateDirective.template;
×
1898
        }
1899
        if (!this._columnPipeArgs.format) {
23,963✔
1900
            this._columnPipeArgs.format = this.dataType === GridColumnDataType.Time ?
22,684✔
1901
                DEFAULT_TIME_FORMAT : this.dataType === GridColumnDataType.DateTime ?
22,414✔
1902
                    DEFAULT_DATE_TIME_FORMAT : DEFAULT_DATE_FORMAT;
1903
        }
1904
        if (!this.summaries) {
23,963✔
1905
            switch (this.dataType) {
22,631✔
1906
                case GridColumnDataType.Number:
1907
                case GridColumnDataType.Currency:
1908
                case GridColumnDataType.Percent:
1909
                    this.summaries = IgxNumberSummaryOperand;
6,894✔
1910
                    break;
6,894✔
1911
                case GridColumnDataType.Date:
1912
                case GridColumnDataType.DateTime:
1913
                    this.summaries = IgxDateSummaryOperand;
1,765✔
1914
                    break;
1,765✔
1915
                case GridColumnDataType.Time:
1916
                    this.summaries = IgxTimeSummaryOperand;
270✔
1917
                    break;
270✔
1918

1919
                case GridColumnDataType.String:
1920
                case GridColumnDataType.Boolean:
1921
                default:
1922
                    this.summaries = IgxSummaryOperand;
13,702✔
1923
                    break;
13,702✔
1924
            }
1925
        }
1926
        if (!this.filters) {
23,963✔
1927
            switch (this.dataType) {
22,391✔
1928
                case GridColumnDataType.Boolean:
1929
                    this.filters = IgxBooleanFilteringOperand.instance();
1,156✔
1930
                    break;
1,156✔
1931
                case GridColumnDataType.Number:
1932
                case GridColumnDataType.Currency:
1933
                case GridColumnDataType.Percent:
1934
                    this.filters = IgxNumberFilteringOperand.instance();
6,937✔
1935
                    break;
6,937✔
1936
                case GridColumnDataType.Date:
1937
                    this.filters = IgxDateFilteringOperand.instance();
1,505✔
1938
                    break;
1,505✔
1939
                case GridColumnDataType.Time:
1940
                    this.filters = IgxTimeFilteringOperand.instance();
270✔
1941
                    break;
270✔
1942
                case GridColumnDataType.DateTime:
1943
                    this.filters = IgxDateTimeFilteringOperand.instance();
266✔
1944
                    break;
266✔
1945
                case GridColumnDataType.Image:
1946
                    this.filterable = false;
1✔
1947
                    break;
1✔
1948
                case GridColumnDataType.String:
1949
                default:
1950
                    this.filters = IgxStringFilteringOperand.instance();
12,256✔
1951
                    break;
12,256✔
1952
            }
1953
        }
1954
    }
1955

1956
    /**
1957
     * @hidden
1958
     */
1959
    public getGridTemplate(isRow: boolean): string {
1960
        if (isRow) {
26,856✔
1961
            const rowsCount = this.grid.type !== 'pivot' ? this.grid.multiRowLayoutRowSize : this.children.length - 1;
13,429!
1962
            return `repeat(${rowsCount},1fr)`;
13,429✔
1963
        } else {
1964
            return this.getColumnSizesString(this.children);
13,427✔
1965
        }
1966
    }
1967

1968
    /** @hidden @internal **/
1969
    public getInitialChildColumnSizes(children: QueryList<IgxColumnComponent>): Array<MRLColumnSizeInfo> {
1970
        const columnSizes: MRLColumnSizeInfo[] = [];
148,166✔
1971
        // find the smallest col spans
1972
        children.forEach(col => {
148,166✔
1973
            if (!col.colStart) {
462,074✔
1974
                return;
106,158✔
1975
            }
1976
            const newWidthSet = col.widthSetByUser && columnSizes[col.colStart - 1] && !columnSizes[col.colStart - 1].widthSetByUser;
355,916✔
1977
            const newSpanSmaller = columnSizes[col.colStart - 1] && columnSizes[col.colStart - 1].colSpan > col.gridColumnSpan;
355,916✔
1978
            const bothWidthsSet = col.widthSetByUser && columnSizes[col.colStart - 1] && columnSizes[col.colStart - 1].widthSetByUser;
355,916✔
1979
            const bothWidthsNotSet = !col.widthSetByUser && columnSizes[col.colStart - 1] && !columnSizes[col.colStart - 1].widthSetByUser;
355,916✔
1980

1981
            if (columnSizes[col.colStart - 1] === undefined) {
355,916✔
1982
                // If nothing is defined yet take any column at first
1983
                // We use colEnd to know where the column actually ends, because not always it starts where we have it set in columnSizes.
1984
                columnSizes[col.colStart - 1] = {
218,549✔
1985
                    ref: col,
1986
                    width: col.width === 'fit-content' ? col.autoSize :
218,549!
1987
                        col.widthSetByUser || this.grid.columnWidthSetByUser ? parseFloat(col.calcWidth) : null,
639,014✔
1988
                    colSpan: col.gridColumnSpan,
1989
                    colEnd: col.colStart + col.gridColumnSpan,
1990
                    widthSetByUser: col.widthSetByUser
1991
                };
1992
            } else if (newWidthSet || (newSpanSmaller && ((bothWidthsSet) || (bothWidthsNotSet)))) {
137,367✔
1993
                // If a column is set already it should either not have width defined or have width with bigger span than the new one.
1994

1995
                /**
1996
                 *  If replaced column has bigger span, we want to fill the remaining columns
1997
                 *  that the replacing column does not fill with the old one.
1998
                 */
1999
                if (bothWidthsSet && newSpanSmaller) {
49,208✔
2000
                    // Start from where the new column set would end and apply the old column to the rest depending on how much it spans.
2001
                    // We have not yet replaced it so we can use it directly from the columnSizes collection.
2002
                    // This is where colEnd is used because the colStart of the old column is not actually i + 1.
2003
                    for (let i = col.colStart - 1 + col.gridColumnSpan; i < columnSizes[col.colStart - 1].colEnd - 1; i++) {
4,796✔
2004
                        if (!columnSizes[i] || !columnSizes[i].widthSetByUser) {
2,743✔
2005
                            columnSizes[i] = columnSizes[col.colStart - 1];
2,693✔
2006
                        } else {
2007
                            break;
50✔
2008
                        }
2009
                    }
2010
                }
2011

2012
                // Replace the old column with the new one.
2013
                columnSizes[col.colStart - 1] = {
49,208✔
2014
                    ref: col,
2015
                    width: col.width === 'fit-content' ? col.autoSize :
49,208!
2016
                        col.widthSetByUser || this.grid.columnWidthSetByUser ? parseFloat(col.calcWidth) : null,
139,184✔
2017
                    colSpan: col.gridColumnSpan,
2018
                    colEnd: col.colStart + col.gridColumnSpan,
2019
                    widthSetByUser: col.widthSetByUser
2020
                };
2021
            } else if (bothWidthsSet && columnSizes[col.colStart - 1].colSpan < col.gridColumnSpan) {
88,159✔
2022
                // If the column already in the columnSizes has smaller span, we still need to fill any empty places with the current col.
2023
                // Start from where the smaller column set would end and apply the bigger column to the rest depending on how much it spans.
2024
                // Since here we do not have it in columnSizes we set it as a new column keeping the same colSpan.
2025
                for (let i = col.colStart - 1 + columnSizes[col.colStart - 1].colSpan; i < col.colStart - 1 + col.gridColumnSpan; i++) {
3,481✔
2026
                    if (!columnSizes[i] || !columnSizes[i].widthSetByUser) {
3,481✔
2027
                        columnSizes[i] = {
47✔
2028
                            ref: col,
2029
                            width: col.width === 'fit-content' ? col.autoSize :
47!
2030
                                col.widthSetByUser || this.grid.columnWidthSetByUser ? parseFloat(col.calcWidth) : null,
94!
2031
                            colSpan: col.gridColumnSpan,
2032
                            colEnd: col.colStart + col.gridColumnSpan,
2033
                            widthSetByUser: col.widthSetByUser
2034
                        };
2035
                    } else {
2036
                        break;
3,434✔
2037
                    }
2038
                }
2039
            }
2040
        });
2041

2042
        // Flatten columnSizes so there are not columns with colSpan > 1
2043
        for (let i = 0; i < columnSizes.length; i++) {
148,166✔
2044
            if (columnSizes[i] && columnSizes[i].colSpan > 1) {
216,695✔
2045
                let j = 1;
10,823✔
2046

2047
                // Replace all empty places depending on how much the current column spans starting from next col.
2048
                for (; j < columnSizes[i].colSpan && i + j + 1 < columnSizes[i].colEnd; j++) {
10,823✔
2049
                    if (columnSizes[i + j] &&
10,432✔
2050
                        ((!columnSizes[i].width && columnSizes[i + j].width) ||
2051
                            (!columnSizes[i].width && !columnSizes[i + j].width && columnSizes[i + j].colSpan <= columnSizes[i].colSpan) ||
2052
                            (!!columnSizes[i + j].width && columnSizes[i + j].colSpan <= columnSizes[i].colSpan))) {
2053
                        // If we reach an already defined column that has width and the current doesn't have or
2054
                        // if the reached column has bigger colSpan we stop.
2055
                        break;
4,411✔
2056
                    } else {
2057
                        const width = columnSizes[i].widthSetByUser ?
6,021✔
2058
                            columnSizes[i].width / columnSizes[i].colSpan :
2059
                            columnSizes[i].width;
2060
                        columnSizes[i + j] = {
6,021✔
2061
                            ref: columnSizes[i].ref,
2062
                            width,
2063
                            colSpan: 1,
2064
                            colEnd: columnSizes[i].colEnd,
2065
                            widthSetByUser: columnSizes[i].widthSetByUser
2066
                        };
2067
                    }
2068
                }
2069

2070
                // Update the current column width so it is divided between all columns it spans and set it to 1.
2071
                columnSizes[i].width = columnSizes[i].widthSetByUser ?
10,823✔
2072
                    columnSizes[i].width / columnSizes[i].colSpan :
2073
                    columnSizes[i].width;
2074
                columnSizes[i].colSpan = 1;
10,823✔
2075

2076
                // Update the index based on how much we have replaced. Subtract 1 because we started from 1.
2077
                i += j - 1;
10,823✔
2078
            }
2079
        }
2080

2081
        return columnSizes;
148,166✔
2082
    }
2083

2084
    /** @hidden @internal **/
2085
    public getFilledChildColumnSizes(children: QueryList<IgxColumnComponent>): Array<string> {
2086
        const columnSizes = this.getInitialChildColumnSizes(children);
25,885✔
2087

2088
        // fill the gaps if there are any
2089
        const result: string[] = [];
25,885✔
2090
        for (const size of columnSizes) {
25,885✔
2091
            if (size && !!size.width) {
57,677✔
2092
                result.push(size.width + 'px');
22,563✔
2093
            } else {
2094
                result.push(parseFloat(this.grid.getPossibleColumnWidth()) + 'px');
35,114✔
2095
            }
2096
        }
2097
        return result;
25,885✔
2098
    }
2099

2100
    /** @hidden @internal **/
2101
    public getResizableColUnderEnd(): MRLResizeColumnInfo[] {
2102
        if (this.columnLayout || !this.columnLayoutChild || this.columnGroup) {
6!
2103
            return [{ target: this, spanUsed: 1 }];
×
2104
        }
2105

2106
        const columnSized = this.getInitialChildColumnSizes(this.parent.children);
6✔
2107
        const targets: MRLResizeColumnInfo[] = [];
6✔
2108
        const colEnd = this.colEnd ? this.colEnd : this.colStart + 1;
6!
2109

2110
        for (let i = 0; i < columnSized.length; i++) {
6✔
2111
            if (this.colStart <= i + 1 && i + 1 < colEnd) {
36✔
2112
                targets.push({ target: columnSized[i].ref, spanUsed: 1 });
10✔
2113
            }
2114
        }
2115

2116
        const targetsSquashed: MRLResizeColumnInfo[] = [];
6✔
2117
        for (const target of targets) {
6✔
2118
            if (targetsSquashed.length && targetsSquashed[targetsSquashed.length - 1].target.field === target.target.field) {
10!
2119
                targetsSquashed[targetsSquashed.length - 1].spanUsed++;
×
2120
            } else {
2121
                targetsSquashed.push(target);
10✔
2122
            }
2123
        }
2124

2125
        return targetsSquashed;
6✔
2126
    }
2127

2128
    /**
2129
     * Pins the column at the provided index in the pinned area.
2130
     * Defaults to index `0` if not provided, or to the initial index in the pinned area.
2131
     * Returns `true` if the column is successfully pinned. Returns `false` if the column cannot be pinned.
2132
     * Column cannot be pinned if:
2133
     * - Is already pinned
2134
     * - index argument is out of range
2135
     * - The pinned area exceeds 80% of the grid width
2136
     * ```typescript
2137
     * let success = this.column.pin();
2138
     * ```
2139
     *
2140
     * @memberof IgxColumnComponent
2141
     */
2142
    public pin(index?: number): boolean {
2143
        // TODO: Probably should the return type of the old functions
2144
        // should be moved as a event parameter.
2145
        const grid = (this.grid as any);
613✔
2146
        if (this._pinned) {
613✔
2147
            return false;
56✔
2148
        }
2149

2150
        if (this.parent && !this.parent.pinned) {
557✔
2151
            return this.topLevelParent.pin(index);
10✔
2152
        }
2153

2154
        const hasIndex = index !== undefined;
547✔
2155
        if (hasIndex && (index < 0 || index > grid.pinnedColumns.length)) {
547✔
2156
            return false;
2✔
2157
        }
2158

2159
        if (!this.parent && !this.pinnable) {
545!
2160
            return false;
×
2161
        }
2162

2163
        const rootPinnedCols = grid._pinnedColumns.filter((c) => c.level === 0);
1,050✔
2164
        index = hasIndex ? index : rootPinnedCols.length;
545✔
2165
        const args: IPinColumnCancellableEventArgs = { column: this, insertAtIndex: index, isPinned: false, cancel: false };
545✔
2166
        this.grid.columnPin.emit(args);
545✔
2167

2168
        if (args.cancel) {
545!
2169
            return;
×
2170
        }
2171

2172
        this.grid.crudService.endEdit(false);
545✔
2173

2174
        this._pinned = true;
545✔
2175
        this.pinnedChange.emit(this._pinned);
545✔
2176
        // it is possible that index is the last position, so will need to find target column by [index-1]
2177
        const targetColumn = args.insertAtIndex === grid._pinnedColumns.length ?
545✔
2178
            grid._pinnedColumns[args.insertAtIndex - 1] : grid._pinnedColumns[args.insertAtIndex];
2179

2180
        if (grid._pinnedColumns.indexOf(this) === -1) {
545✔
2181
            if (!grid.hasColumnGroups) {
420✔
2182
                grid._pinnedColumns.splice(args.insertAtIndex, 0, this);
371✔
2183
            } else {
2184
                // insert based only on root collection
2185
                if (this.level === 0) {
49✔
2186
                    rootPinnedCols.splice(args.insertAtIndex, 0, this);
42✔
2187
                }
2188
                let allPinned = [];
49✔
2189
                // FIX: this is duplicated on every step in the hierarchy....
2190
                // re-create hierarchy
2191
                rootPinnedCols.forEach(group => {
49✔
2192
                    allPinned.push(group);
79✔
2193
                    allPinned = allPinned.concat(group.allChildren);
79✔
2194
                });
2195
                grid._pinnedColumns = allPinned;
49✔
2196
            }
2197

2198
            if (grid._unpinnedColumns.indexOf(this) !== -1) {
420✔
2199
                const childrenCount = this.allChildren.length;
189✔
2200
                grid._unpinnedColumns.splice(grid._unpinnedColumns.indexOf(this), 1 + childrenCount);
189✔
2201
            }
2202
        }
2203

2204
        if (hasIndex) {
545✔
2205
            index === grid._pinnedColumns.length - 1 ?
10✔
2206
                grid._moveColumns(this, targetColumn, DropPosition.AfterDropTarget) : grid._moveColumns(this, targetColumn, DropPosition.BeforeDropTarget);
2207
        }
2208

2209
        if (this.columnGroup) {
545✔
2210
            this.allChildren.forEach(child => child.pin());
186✔
2211
            grid.reinitPinStates();
59✔
2212
        }
2213

2214
        grid.resetCaches();
545✔
2215
        grid.notifyChanges();
545✔
2216
        if (this.columnLayoutChild) {
545✔
2217
            this.grid.columns.filter(x => x.columnLayout).forEach(x => x.populateVisibleIndexes());
407✔
2218
        }
2219
        this.grid.filteringService.refreshExpressions();
545✔
2220
        const eventArgs: IPinColumnEventArgs = { column: this, insertAtIndex: index, isPinned: true };
545✔
2221
        this.grid.columnPinned.emit(eventArgs);
545✔
2222
        return true;
545✔
2223
    }
2224
    /**
2225
     * Unpins the column and place it at the provided index in the unpinned area.
2226
     * Defaults to index `0` if not provided, or to the initial index in the unpinned area.
2227
     * Returns `true` if the column is successfully unpinned. Returns `false` if the column cannot be unpinned.
2228
     * Column cannot be unpinned if:
2229
     * - Is already unpinned
2230
     * - index argument is out of range
2231
     * ```typescript
2232
     * let success = this.column.unpin();
2233
     * ```
2234
     *
2235
     * @memberof IgxColumnComponent
2236
     */
2237
    public unpin(index?: number): boolean {
2238
        const grid = (this.grid as any);
188✔
2239
        if (!this._pinned) {
188✔
2240
            return false;
32✔
2241
        }
2242

2243
        if (this.parent && this.parent.pinned) {
156✔
2244
            return this.topLevelParent.unpin(index);
7✔
2245
        }
2246
        const hasIndex = index !== undefined;
149✔
2247
        if (hasIndex && (index < 0 || index > grid._unpinnedColumns.length)) {
149✔
2248
            return false;
2✔
2249
        }
2250

2251
        // estimate the exact index at which column will be inserted
2252
        // takes into account initial unpinned index of the column
2253
        if (!hasIndex) {
147✔
2254
            const indices = grid.unpinnedColumns.map(col => col.index);
1,184✔
2255
            indices.push(this.index);
143✔
2256
            indices.sort((a, b) => a - b);
1,560✔
2257
            index = indices.indexOf(this.index);
143✔
2258
        }
2259

2260
        const args: IPinColumnCancellableEventArgs = { column: this, insertAtIndex: index, isPinned: true, cancel: false };
147✔
2261
        this.grid.columnPin.emit(args);
147✔
2262

2263
        if (args.cancel) {
147!
2264
            return;
×
2265
        }
2266

2267
        this.grid.crudService.endEdit(false);
147✔
2268

2269
        this._pinned = false;
147✔
2270
        this.pinnedChange.emit(this._pinned);
147✔
2271

2272
        // it is possible that index is the last position, so will need to find target column by [index-1]
2273
        const targetColumn = args.insertAtIndex === grid._unpinnedColumns.length ?
147✔
2274
            grid._unpinnedColumns[args.insertAtIndex - 1] : grid._unpinnedColumns[args.insertAtIndex];
2275

2276
        if (!hasIndex) {
147✔
2277
            grid._unpinnedColumns.splice(index, 0, this);
143✔
2278
            if (grid._pinnedColumns.indexOf(this) !== -1) {
143✔
2279
                grid._pinnedColumns.splice(grid._pinnedColumns.indexOf(this), 1);
143✔
2280
            }
2281
        }
2282

2283
        if (hasIndex) {
147✔
2284
            grid.moveColumn(this, targetColumn);
4✔
2285
        }
2286

2287
        if (this.columnGroup) {
147✔
2288
            this.allChildren.forEach(child => child.unpin());
106✔
2289
        }
2290

2291
        grid.reinitPinStates();
147✔
2292
        grid.resetCaches();
147✔
2293

2294
        grid.notifyChanges();
147✔
2295
        if (this.columnLayoutChild) {
147✔
2296
            this.grid.columns.filter(x => x.columnLayout).forEach(x => x.populateVisibleIndexes());
356✔
2297
        }
2298
        this.grid.filteringService.refreshExpressions();
147✔
2299

2300
        this.grid.columnPinned.emit({ column: this, insertAtIndex: index, isPinned: false });
147✔
2301

2302
        return true;
147✔
2303
    }
2304

2305
    /**
2306
     * Moves a column to the specified visible index.
2307
     * If passed index is invalid, or if column would receive a different visible index after moving, moving is not performed.
2308
     * If passed index would move the column to a different column group. moving is not performed.
2309
     *
2310
     * @example
2311
     * ```typescript
2312
     * column.move(index);
2313
     * ```
2314
     * @memberof IgxColumnComponent
2315
     */
2316
    public move(index: number) {
2317
        let target;
2318
        let columns = this.grid.columns.filter(c => c.visibleIndex > -1);
349✔
2319
        // grid last visible index
2320
        const li = columns.map(c => c.visibleIndex).reduce((a, b) => Math.max(a, b));
343✔
2321
        const parent = this.parent;
36✔
2322
        const isPreceding = this.visibleIndex < index;
36✔
2323

2324
        if (index === this.visibleIndex || index < 0 || index > li) {
36✔
2325
            return;
3✔
2326
        }
2327

2328
        if (parent) {
33✔
2329
            columns = columns.filter(c => c.level >= this.level && c !== this && c.parent !== this &&
84✔
2330
                c.topLevelParent === this.topLevelParent);
2331
        }
2332

2333
        // If isPreceding, find a target such that when the current column is placed after it, current colummn will receive a visibleIndex === index. This takes into account visible children of the columns.
2334
        // If !isPreceding, finds a column of the same level and visible index that equals the passed index agument (c.visibleIndex === index). No need to consider the children here.
2335

2336
        if (isPreceding) {
33✔
2337
            columns = columns.filter(c => c.visibleIndex > this.visibleIndex);
200✔
2338
            target = columns.find(c => c.level === this.level && c.visibleIndex + (c as any).calcChildren() - this.calcChildren() === index);
80✔
2339
        } else {
2340
            columns = columns.filter(c => c.visibleIndex < this.visibleIndex);
65✔
2341
            target = columns.find(c => c.level === this.level && c.visibleIndex === index);
15✔
2342
        }
2343

2344
        if (!target || (target.pinned && this.disablePinning)) {
33✔
2345
            return;
9✔
2346
        }
2347

2348
        const pos = isPreceding ? DropPosition.AfterDropTarget : DropPosition.BeforeDropTarget;
24✔
2349
        this.grid.moveColumn(this, target as IgxColumnComponent, pos);
24✔
2350
    }
2351

2352
    /**
2353
     * No children for the column, so will returns 1 or 0, if the column is hidden.
2354
     *
2355
     * @hidden
2356
     */
2357
    public calcChildren(): number {
2358
        const children = this.hidden ? 0 : 1;
70✔
2359
        return children;
70✔
2360
    }
2361

2362
    /**
2363
     * Toggles column vibisility and emits the respective event.
2364
     *
2365
     * @hidden
2366
     */
2367
    public toggleVisibility(value?: boolean) {
2368
        const newValue = value ?? !this.hidden;
65✔
2369
        const eventArgs: IColumnVisibilityChangingEventArgs = { column: this, newValue, cancel: false };
65✔
2370
        this.grid.columnVisibilityChanging.emit(eventArgs);
65✔
2371

2372
        if (eventArgs.cancel) {
65!
2373
            return;
×
2374
        }
2375
        this.hidden = newValue;
65✔
2376
        this.grid.columnVisibilityChanged.emit({ column: this, newValue });
65✔
2377
    }
2378

2379
    /**
2380
     * Returns a reference to the top level parent column.
2381
     * ```typescript
2382
     * let topLevelParent =  this.column.topLevelParent;
2383
     * ```
2384
     */
2385
    public get topLevelParent(): ColumnType | undefined {
2386
        let parent = this.parent;
490✔
2387
        while (parent && parent.parent) {
490✔
2388
            parent = parent.parent;
34✔
2389
        }
2390
        return parent ?? undefined;
490✔
2391
    }
2392

2393
    /**
2394
     * @hidden @internal
2395
     */
2396
    public get headerCell(): IgxGridHeaderComponent {
2397
        return this.grid.headerCellList.find((header) => header.column === this);
1,574✔
2398
    }
2399

2400
    /**
2401
     * @hidden @internal
2402
     */
2403
    public get filterCell(): IgxGridFilteringCellComponent {
2404
        return this.grid.filterCellList.find((filterCell) => filterCell.column === this);
6,929✔
2405
    }
2406

2407
    /**
2408
     * @hidden @internal
2409
     */
2410
    public get headerGroup(): IgxGridHeaderGroupComponent {
2411
        return this.grid.headerGroupsList.find(group => group.column === this);
6,275✔
2412
    }
2413

2414
    /**
2415
     * Autosize the column to the longest currently visible cell value, including the header cell.
2416
     * ```typescript
2417
     * @ViewChild('grid') grid: IgxGridComponent;
2418
     * let column = this.grid.columnList.filter(c => c.field === 'ID')[0];
2419
     * column.autosize();
2420
     * ```
2421
     *
2422
     * @memberof IgxColumnComponent
2423
     * @param byHeaderOnly Set if column should be autosized based only on the header content.
2424
     */
2425
    public autosize(byHeaderOnly = false) {
17✔
2426
        if (!this.columnGroup) {
18✔
2427
            this.width = this.getAutoSize(byHeaderOnly);
18✔
2428
            this.grid.reflow();
18✔
2429
        }
2430
    }
2431

2432
    /**
2433
     * @hidden
2434
     */
2435
    public getAutoSize(byHeader = false): string {
8✔
2436
        const size = !byHeader ? this.getLargestCellWidth() :
26✔
2437
            (Object.values(this.getHeaderCellWidths()).reduce((a, b) => a + b) + 'px');
1✔
2438
        const isPercentageWidth = this.width && typeof this.width === 'string' && this.width.indexOf('%') !== -1;
26✔
2439

2440
        let newWidth;
2441
        if (isPercentageWidth) {
26✔
2442
            const gridAvailableSize = this.grid.calcWidth;
2✔
2443
            const percentageSize = parseFloat(size) / gridAvailableSize * 100;
2✔
2444
            newWidth = percentageSize + '%';
2✔
2445
        } else {
2446
            newWidth = size;
24✔
2447
        }
2448

2449
        const maxWidth = isPercentageWidth ? this.maxWidthPercent : this.maxWidthPx;
26✔
2450
        const minWidth = isPercentageWidth ? this.minWidthPercent : this.minWidthPx;
26✔
2451
        if (this.maxWidth && (parseFloat(newWidth) > maxWidth)) {
26✔
2452
            newWidth = isPercentageWidth ? maxWidth + '%' : maxWidth + 'px';
1!
2453
        } else if (parseFloat(newWidth) < minWidth) {
25✔
2454
            newWidth = isPercentageWidth ? minWidth + '%' : minWidth + 'px';
1!
2455
        }
2456

2457
        return newWidth;
26✔
2458
    }
2459

2460
    /**
2461
     * @hidden
2462
     */
2463
    public getCalcWidth(): any {
2464
        if (this._calcWidth && !isNaN(this.calcPixelWidth)) {
237,379✔
2465
            return this._calcWidth;
231,129✔
2466
        }
2467
        this.cacheCalcWidth();
6,250✔
2468
        return this._calcWidth;
6,250✔
2469
    }
2470

2471

2472
    /**
2473
     * @hidden
2474
     * Returns the width and padding of a header cell.
2475
     */
2476
    public getHeaderCellWidths() {
2477
        return this.grid.getHeaderCellWidth(this.headerCell.nativeElement);
25✔
2478
    }
2479

2480
    /**
2481
     * @hidden
2482
     * Returns the size (in pixels) of the longest currently visible cell, including the header cell.
2483
     * ```typescript
2484
     * @ViewChild('grid') grid: IgxGridComponent;
2485
     *
2486
     * let column = this.grid.columnList.filter(c => c.field === 'ID')[0];
2487
     * let size = column.getLargestCellWidth();
2488
     * ```
2489
     * @memberof IgxColumnComponent
2490
     */
2491
    public getLargestCellWidth(): string {
2492
        const range = this.grid.document.createRange();
25✔
2493
        const largest = new Map<number, number>();
25✔
2494

2495
        if (this._cells.length > 0) {
25✔
2496
            const cellsContentWidths = [];
25✔
2497
            this._cells.forEach((cell) => cellsContentWidths.push(cell.calculateSizeToFit(range)));
270✔
2498

2499
            const index = cellsContentWidths.indexOf(Math.max(...cellsContentWidths));
25✔
2500
            const cellStyle = this.grid.document.defaultView.getComputedStyle(this._cells[index].nativeElement);
25✔
2501
            const cellPadding = parseFloat(cellStyle.paddingLeft) + parseFloat(cellStyle.paddingRight) +
25✔
2502
                parseFloat(cellStyle.borderLeftWidth) + parseFloat(cellStyle.borderRightWidth);
2503

2504
            largest.set(Math.max(...cellsContentWidths), cellPadding);
25✔
2505
        }
2506

2507
        if (this.headerCell && this.autosizeHeader) {
25✔
2508
            const headerCellWidths = this.getHeaderCellWidths();
24✔
2509
            largest.set(headerCellWidths.width, headerCellWidths.padding);
24✔
2510
        }
2511

2512
        const largestCell = Math.max(...Array.from(largest.keys()));
25✔
2513
        const width = Math.ceil(largestCell + largest.get(largestCell));
25✔
2514

2515
        if (Number.isNaN(width)) {
25!
2516
            return this.width;
×
2517
        } else {
2518
            return width + 'px';
25✔
2519
        }
2520
    }
2521

2522
    /**
2523
     * @hidden
2524
     */
2525
    public getCellWidth() {
2526
        const colWidth = this.width;
1,159,043✔
2527
        const isPercentageWidth = colWidth && typeof colWidth === 'string' && colWidth.indexOf('%') !== -1;
1,159,043✔
2528

2529
        if (this.columnLayoutChild) {
1,159,043!
2530
            return '';
×
2531
        }
2532

2533
        if (colWidth && !isPercentageWidth) {
1,159,043✔
2534

2535
            let cellWidth = colWidth;
1,147,618✔
2536
            if (typeof cellWidth !== 'string' || cellWidth.endsWith('px') === false) {
1,147,618✔
2537
                cellWidth += 'px';
2,389✔
2538
            }
2539

2540
            return cellWidth;
1,147,618✔
2541
        } else {
2542
            return colWidth;
11,425✔
2543
        }
2544
    }
2545

2546
    /**
2547
     * @hidden
2548
     */
2549
    public populateVisibleIndexes() { }
2550

2551
    protected getColumnSizesString(children: QueryList<IgxColumnComponent>): string {
2552
        const res = this.getFilledChildColumnSizes(children);
13,427✔
2553
        return res.join(' ');
13,427✔
2554
    }
2555

2556
    /**
2557
     * @hidden
2558
     * @internal
2559
     */
2560
    protected cacheCalcWidth(): any {
2561
        const colWidth = this.width;
304,438✔
2562
        const isPercentageWidth = colWidth && typeof colWidth === 'string' && colWidth.indexOf('%') !== -1;
304,438✔
2563
        const isAutoWidth = colWidth && typeof colWidth === 'string' && colWidth === 'fit-content';
304,438✔
2564
        if (isPercentageWidth && this.grid.isColumnWidthSum) {
304,438✔
2565
            this._calcWidth = this.grid.minColumnWidth;
32✔
2566
        } else if (isPercentageWidth) {
304,406✔
2567
            this._calcWidth = parseFloat(colWidth) / 100 * this.grid.calcWidth;
894✔
2568
        } else if (!colWidth || isAutoWidth && !this.autoSize) {
303,512✔
2569
            // no width
2570
            this._calcWidth = this.defaultWidth || this.grid.getPossibleColumnWidth();
26,820✔
2571
        } else {
2572
            this._calcWidth = this.width;
276,692✔
2573
        }
2574
        this.calcPixelWidth = parseFloat(this._calcWidth);
304,438✔
2575
    }
2576

2577
    /**
2578
     * @hidden
2579
     * @internal
2580
     */
2581
    protected setExpandCollapseState() {
2582
        this.children.filter(col => (col.visibleWhenCollapsed !== undefined)).forEach(c => {
295✔
2583
            if (!this.collapsible) {
270✔
2584
                c.hidden = this.hidden; return;
2✔
2585
            }
2586
            c.hidden = this._expanded ? c.visibleWhenCollapsed : !c.visibleWhenCollapsed;
268✔
2587
        });
2588
    }
2589
    /**
2590
     * @hidden
2591
     * @internal
2592
     */
2593
    protected checkCollapsibleState() {
2594
        if (!this.children) {
2,481!
2595
            return false;
×
2596
        }
2597
        const cols = this.children.map(child => child.visibleWhenCollapsed);
6,113✔
2598
        return (cols.some(c => c === true) && cols.some(c => c === false));
3,756✔
2599
    }
2600

2601
    /**
2602
     * @hidden
2603
     */
2604
    public get pinnable() {
2605
        return (this.grid as any)._init || !this.pinned;
401✔
2606
    }
2607

2608
    /**
2609
     * @hidden
2610
     */
2611
    public get applySelectableClass(): boolean {
2612
        return this._applySelectableClass;
10,986✔
2613
    }
2614

2615
    /**
2616
     * @hidden
2617
     */
2618
    public set applySelectableClass(value: boolean) {
2619
        if (this.selectable) {
15✔
2620
            this._applySelectableClass = value;
13✔
2621
        }
2622
    }
2623
}
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