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

IgniteUI / igniteui-angular / 13331632524

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

Pull #15372

github

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

1990 of 15592 branches covered (12.76%)

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

19956 existing lines in 307 files now uncovered.

6452 of 29307 relevant lines covered (22.02%)

249.17 hits per line

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

10.38
/projects/igniteui-angular/src/lib/progressbar/progressbar.component.ts
1
import { NgClass, NgTemplateOutlet } from '@angular/common';
2
import {
3
    Component,
4
    ElementRef,
5
    EventEmitter,
6
    HostBinding,
7
    Input,
8
    Output,
9
    Renderer2,
10
    ViewChild,
11
    ContentChild,
12
    AfterViewInit,
13
    AfterContentInit,
14
    Directive,
15
    booleanAttribute,
16
    inject,
17
    ChangeDetectorRef,
18
    NgZone,
19
} from '@angular/core';
20
import {
21
    IgxProgressBarTextTemplateDirective,
22
    IgxProgressBarGradientDirective,
23
} from './progressbar.common';
24
import { IBaseEventArgs, mkenum } from '../core/utils';
25
const ONE_PERCENT = 0.01;
2✔
26
const MIN_VALUE = 0;
2✔
27

28
export const IgxTextAlign = /*@__PURE__*/mkenum({
2✔
29
    START: 'start',
30
    CENTER: 'center',
31
    END: 'end'
32
});
33
export type IgxTextAlign = (typeof IgxTextAlign)[keyof typeof IgxTextAlign];
34

35
export const IgxProgressType = /*@__PURE__*/mkenum({
2✔
36
    ERROR: 'error',
37
    INFO: 'info',
38
    WARNING: 'warning',
39
    SUCCESS: 'success'
40
});
41
export type IgxProgressType = (typeof IgxProgressType)[keyof typeof IgxProgressType];
42

43
export interface IChangeProgressEventArgs extends IBaseEventArgs {
44
    previousValue: number;
45
    currentValue: number;
46
}
47
export const valueInRange = (value: number, max: number, min = 0): number => Math.max(Math.min(value, max), min);
2!
48

49
/**
50
 * @hidden
51
 */
52
@Directive()
53
export abstract class BaseProgressDirective {
2✔
54
    /**
55
     * An event, which is triggered after progress is changed.
56
     * ```typescript
57
     * public progressChange(event) {
58
     *     alert("Progress made!");
59
     * }
60
     *  //...
61
     * ```
62
     * ```html
63
     * <igx-circular-bar (progressChanged)="progressChange($event)"></igx-circular-bar>
64
     * <igx-linear-bar (progressChanged)="progressChange($event)"></igx-linear-bar>
65
     * ```
66
     */
67
    @Output()
UNCOV
68
    public progressChanged = new EventEmitter<IChangeProgressEventArgs>();
×
69

70
    /**
71
     * Sets/Gets progressbar animation duration. By default, it is 2000ms.
72
     * ```html
73
     * <igx-linear-bar [animationDuration]="3000"></igx-linear-bar>
74
     * <igx-circular-bar [animationDuration]="3000"></igx-linear-bar>
75
     * ```
76
     */
77
    @Input()
UNCOV
78
    public animationDuration = 2000;
×
79

UNCOV
80
    protected _contentInit = false;
×
UNCOV
81
    protected _indeterminate = false;
×
82
    protected _text: string;
UNCOV
83
    protected _max = 100;
×
UNCOV
84
    protected _value = MIN_VALUE;
×
UNCOV
85
    protected _animate = true;
×
86
    protected _step: number;
UNCOV
87
    protected _fraction = 0;
×
UNCOV
88
    protected _integer = 0;
×
UNCOV
89
    protected _cdr = inject(ChangeDetectorRef);
×
UNCOV
90
    protected _zone = inject(NgZone);
×
91

92
    /**
93
     * Sets progressbar in indeterminate. By default, it is set to false.
94
     * ```html
95
     * <igx-linear-bar [indeterminate]="true"></igx-linear-bar>
96
     * <igx-circular-bar [indeterminate]="true"></igx-circular-bar>
97
     * ```
98
     */
99
    @Input({ transform: booleanAttribute })
100
    public set indeterminate(isIndeterminate: boolean) {
UNCOV
101
        this._indeterminate = isIndeterminate;
×
UNCOV
102
        this._resetCounterValues(this._indeterminate); // Use the helper for indeterminate condition
×
103
    }
104

105
    /**
106
     * Gets the current state of the progress bar:
107
     * - `true` if in the indeterminate state (no progress value displayed),
108
     * - `false` if the progress bar shows the actual progress.
109
     *
110
     * ```typescript
111
     * const isIndeterminate = progressBar.indeterminate;
112
     * ```
113
    */
114
    public get indeterminate(): boolean {
UNCOV
115
        return this._indeterminate;
×
116
    }
117

118
    /**
119
     * Returns the value which update the progress indicator of the `progress bar`.
120
     * ```typescript
121
     * @ViewChild("MyProgressBar")
122
     * public progressBar: IgxLinearProgressBarComponent | IgxCircularBarComponent;
123
     * public stepValue(event) {
124
     *     let step = this.progressBar.step;
125
     *     alert(step);
126
     * }
127
     * ```
128
     */
129
    @Input()
130
    public get step(): number {
UNCOV
131
        if (this._step) {
×
UNCOV
132
            return this._step;
×
133
        }
UNCOV
134
        return this._max * ONE_PERCENT;
×
135
    }
136

137
    /**
138
     * Sets the value by which progress indicator is updated. By default, it is 1.
139
     * ```html
140
     * <igx-linear-bar [step]="1"></igx-linear-bar>
141
     * <igx-circular-bar [step]="1"></igx-circular-bar>
142
     * ```
143
     */
144
    public set step(val: number) {
UNCOV
145
        const step = Number(val);
×
UNCOV
146
        if (step > this.max) {
×
UNCOV
147
            return;
×
148
        }
149

UNCOV
150
        this._step = step;
×
151
    }
152

153

154
    /**
155
     * Set a custom text. This will hide the counter value.
156
     * ```html
157
     * <igx-circular-bar text="my text"></igx-circular-bar>
158
     * ```
159
     */
160
    @Input()
161
    public set text(value: string) {
UNCOV
162
        this._text = value;
×
UNCOV
163
        this._resetCounterValues(!!this._text); // Use the helper for text condition
×
164
    }
165

166
    /**
167
     * Gets a custom text.
168
     * ```typescript
169
     * let text = this.circularBar.text;
170
     * ```
171
     */
172
    public get text(): string {
UNCOV
173
        return this._text;
×
174
    }
175

176
    /**
177
     * Animating the progress. By default, it is set to true.
178
     * ```html
179
     * <igx-linear-bar [animate]="false"></igx-linear-bar>
180
     * <igx-circular-bar [animate]="false"></igx-circular-bar>
181
     * ```
182
     */
183
    @Input({ transform: booleanAttribute })
184
    public set animate(animate: boolean) {
UNCOV
185
        this._animate = animate;
×
186
    }
187

188
    /**
189
     * Returns whether the `progress bar` has animation true/false.
190
     * ```typescript
191
     * @ViewChild("MyProgressBar")
192
     * public progressBar: IgxLinearProgressBarComponent | IgxCircularBarComponent;
193
     * public animationStatus(event) {
194
     *     let animationStatus = this.progressBar.animate;
195
     *     alert(animationStatus);
196
     * }
197
     * ```
198
     */
199
    public get animate(): boolean {
UNCOV
200
        return this._animate;
×
201
    }
202

203
    /**
204
     * Set maximum value that can be passed. By default it is set to 100.
205
     * ```html
206
     * <igx-linear-bar [max]="200"></igx-linear-bar>
207
     * <igx-circular-bar [max]="200"></igx-circular-bar>
208
     * ```
209
     */
210
    @HostBinding('attr.aria-valuemax')
211
    @Input()
212
    public set max(maxNum: number) {
213
        // Ignore invalid or unchanged max
UNCOV
214
        if (maxNum < MIN_VALUE || this._max === maxNum) {
×
UNCOV
215
            return;
×
216
        }
217

UNCOV
218
        this._max = maxNum;
×
219

220
        // Revalidate current value
UNCOV
221
        this._value = valueInRange(this._value, this._max);
×
222

223
        // Refresh CSS variables
UNCOV
224
        this._updateProgressValues();
×
225
    }
226

227
    /**
228
     * Returns the maximum progress value of the `progress bar`.
229
     * ```typescript
230
     * @ViewChild("MyProgressBar")
231
     * public progressBar: IgxLinearProgressBarComponent | IgxCircularBarComponent;
232
     * public maxValue(event) {
233
     *     let max = this.progressBar.max;
234
     *     alert(max);
235
     * }
236
     * ```
237
     */
238
    public get max() {
UNCOV
239
        return this._max;
×
240
    }
241

242
    @HostBinding('style.--_progress-integer')
243
    private get progressInteger() {
UNCOV
244
        return this._integer.toString();
×
245
    }
246

247
    @HostBinding('style.--_progress-fraction')
248
    private get progressFraction() {
UNCOV
249
        return this._fraction.toString();
×
250
    }
251

252
    @HostBinding('style.--_progress-whole')
253
    private get progressWhole() {
UNCOV
254
        return this.valueInPercent.toFixed(2);
×
255
    }
256

257
    @HostBinding('style.--_transition-duration')
258
    private get transitionDuration() {
UNCOV
259
        return `${this.animationDuration}ms`;
×
260
    }
261

262
    /**
263
     * @hidden
264
     */
265
    protected get hasFraction(): boolean {
UNCOV
266
        const percentage = this.valueInPercent;
×
UNCOV
267
        const integerPart = Math.floor(percentage);
×
UNCOV
268
        const fractionalPart = percentage - integerPart;
×
269

UNCOV
270
        return fractionalPart > 0;
×
271
    }
272

273
    /**
274
     * Returns the `IgxLinearProgressBarComponent`/`IgxCircularProgressBarComponent` value in percentage.
275
     * ```typescript
276
     * @ViewChild("MyProgressBar")
277
     * public progressBar: IgxLinearProgressBarComponent / IgxCircularProgressBarComponent
278
     * public valuePercent(event){
279
     *     let percentValue = this.progressBar.valueInPercent;
280
     *     alert(percentValue);
281
     * }
282
     * ```
283
     */
284
    public get valueInPercent(): number {
UNCOV
285
        const result = this.max > 0 ? (this._value / this.max) * 100 : 0;
×
UNCOV
286
        return Math.round(result * 100) / 100; // Round to two decimal places
×
287
    }
288

289
    /**
290
     * Returns value that indicates the current `IgxLinearProgressBarComponent`/`IgxCircularProgressBarComponent` position.
291
     * ```typescript
292
     * @ViewChild("MyProgressBar")
293
     * public progressBar: IgxLinearProgressBarComponent / IgxCircularProgressBarComponent;
294
     * public getValue(event) {
295
     *     let value = this.progressBar.value;
296
     *     alert(value);
297
     * }
298
     * ```
299
     */
300
    @HostBinding('attr.aria-valuenow')
301
    @Input()
302
    public get value(): number {
UNCOV
303
        return this._value;
×
304
    }
305

306
    /**
307
     * @hidden
308
     */
309
    protected _updateProgressValues(): void {
UNCOV
310
        const percentage = this.valueInPercent;
×
UNCOV
311
        const integerPart = Math.floor(percentage);
×
UNCOV
312
        const fractionalPart = Math.round((percentage % 1) * 100);
×
313

UNCOV
314
        this._integer = integerPart;
×
UNCOV
315
        this._fraction = fractionalPart;
×
316
    }
317

318
    private _resetCounterValues(condition: boolean) {
UNCOV
319
        if (condition) {
×
UNCOV
320
            this._integer = 0;
×
UNCOV
321
            this._fraction = 0;
×
322
        } else {
UNCOV
323
            this._zone.runOutsideAngular(() => {
×
UNCOV
324
                setTimeout(() => {
×
UNCOV
325
                    this._updateProgressValues();
×
UNCOV
326
                    this._cdr.markForCheck();
×
327
                });
328
            });
329
        }
330
    }
331

332
    /**
333
     * Set value that indicates the current `IgxLinearProgressBarComponent / IgxCircularProgressBarComponent` position.
334
     * ```html
335
     * <igx-linear-bar [value]="50"></igx-linear-bar>
336
     * <igx-circular-bar [value]="50"></igx-circular-bar>
337
     * ```
338
     */
339
    public set value(val) {
UNCOV
340
        const valInRange = valueInRange(val, this.max); // Ensure value is in range
×
341

342
        // Avoid redundant updates
UNCOV
343
        if (isNaN(valInRange) || this._value === valInRange) {
×
UNCOV
344
            return;
×
345
        }
346

UNCOV
347
        const previousValue = this._value;
×
348

349
        // Update internal value
UNCOV
350
        this._value = valInRange;
×
351

UNCOV
352
        this._zone.runOutsideAngular(() => {
×
UNCOV
353
            setTimeout(() => {
×
UNCOV
354
                this._updateProgressValues();
×
UNCOV
355
                this._cdr.markForCheck();
×
356
            });
357
        });
358

359
        // Emit the progressChanged event
UNCOV
360
        this.progressChanged.emit({
×
361
            previousValue,
362
            currentValue: this._value,
363
        });
364
    }
365
}
366
let NEXT_LINEAR_ID = 0;
2✔
367
let NEXT_CIRCULAR_ID = 0;
2✔
368
let NEXT_GRADIENT_ID = 0;
2✔
369
@Component({
370
    selector: 'igx-linear-bar',
371
    templateUrl: 'templates/linear-bar.component.html',
372
    imports: [NgClass]
373
})
374
export class IgxLinearProgressBarComponent extends BaseProgressDirective implements AfterContentInit {
2✔
375
    @HostBinding('attr.aria-valuemin')
UNCOV
376
    public valueMin = 0;
×
377

378
    @HostBinding('class.igx-linear-bar')
UNCOV
379
    public cssClass = 'igx-linear-bar';
×
380

381
    /**
382
     * Set `IgxLinearProgressBarComponent` to have striped style. By default it is set to false.
383
     * ```html
384
     * <igx-linear-bar [striped]="true" [max]="200" [value]="50"></igx-linear-bar>
385
     * ```
386
     */
387
    @HostBinding('class.igx-linear-bar--striped')
388
    @Input({ transform: booleanAttribute })
UNCOV
389
    public striped = false;
×
390

391
    /**
392
     * @hidden
393
     * ```
394
     */
395
    @HostBinding('class.igx-linear-bar--indeterminate')
396
    public get isIndeterminate() {
UNCOV
397
        return this.indeterminate;
×
398
    }
399

400
    /**
401
     * Sets the value of the `role` attribute. If not provided it will be automatically set to `progressbar`.
402
     * ```html
403
     * <igx-linear-bar role="progressbar"></igx-linear-bar>
404
     * ```
405
     */
406
    @HostBinding('attr.role')
407
    @Input()
UNCOV
408
    public role = 'progressbar';
×
409

410
    /**
411
     * Sets the value of `id` attribute. If not provided it will be automatically generated.
412
     * ```html
413
     * <igx-linear-bar [id]="'igx-linear-bar-55'" [striped]="true" [max]="200" [value]="50"></igx-linear-bar>
414
     * ```
415
     */
416
    @HostBinding('attr.id')
417
    @Input()
UNCOV
418
    public id = `igx-linear-bar-${NEXT_LINEAR_ID++}`;
×
419

420
    /**
421
     * @hidden
422
     */
423
    @HostBinding('class.igx-linear-bar--animation-none')
424
    public get disableAnimationClass(): boolean {
UNCOV
425
        return !this._animate;
×
426
    }
427

428
    /**
429
     * @hidden
430
     */
431
    @HostBinding('class.igx-linear-bar--hide-counter')
432
    public get hasText(): boolean {
UNCOV
433
        return !!this.text;
×
434
    }
435

436
    /**
437
     * Set the position that defines where the text is aligned.
438
     * Possible options - `IgxTextAlign.START` (default), `IgxTextAlign.CENTER`, `IgxTextAlign.END`.
439
     * ```typescript
440
     * public positionCenter: IgxTextAlign;
441
     * public ngOnInit() {
442
     *     this.positionCenter = IgxTextAlign.CENTER;
443
     * }
444
     *  //...
445
     * ```
446
     *  ```html
447
     * <igx-linear-bar [textAlign]="positionCenter"></igx-linear-bar>
448
     * ```
449
     */
450
    @Input()
UNCOV
451
    public textAlign: IgxTextAlign = IgxTextAlign.START;
×
452

453
    /**
454
     * Set the text to be visible. By default, it is set to true.
455
     * ```html
456
     *  <igx-linear-bar [textVisibility]="false"></igx-linear-bar>
457
     * ```
458
     */
459
    @Input({ transform: booleanAttribute })
UNCOV
460
    public textVisibility = true;
×
461

462
    /**
463
     * Set the position that defines if the text should be aligned above the progress line. By default, is set to false.
464
     * ```html
465
     *  <igx-linear-bar [textTop]="true"></igx-linear-bar>
466
     * ```
467
     */
468
    @Input({ transform: booleanAttribute })
UNCOV
469
    public textTop = false;
×
470

471
    /**
472
     * Set type of the `IgxLinearProgressBarComponent`. Possible options - `default`, `success`, `info`, `warning`, and `error`.
473
     * ```html
474
     * <igx-linear-bar [type]="'error'"></igx-linear-bar>
475
     * ```
476
     */
477
    @Input()
UNCOV
478
    public type = 'default';
×
479

480
    /**
481
     * @hidden
482
     */
483
    @HostBinding('class.igx-linear-bar--danger')
484
    public get error() {
UNCOV
485
        return this.type === IgxProgressType.ERROR;
×
486
    }
487

488
    /**
489
     * @hidden
490
     */
491
    @HostBinding('class.igx-linear-bar--info')
492
    public get info() {
UNCOV
493
        return this.type === IgxProgressType.INFO;
×
494
    }
495

496
    /**
497
     * @hidden
498
     */
499
    @HostBinding('class.igx-linear-bar--warning')
500
    public get warning() {
UNCOV
501
        return this.type === IgxProgressType.WARNING;
×
502
    }
503

504
    /**
505
     * @hidden
506
     */
507
    @HostBinding('class.igx-linear-bar--success')
508
    public get success() {
UNCOV
509
        return this.type === IgxProgressType.SUCCESS;
×
510
    }
511

512
    public ngAfterContentInit() {
UNCOV
513
        this._contentInit = true;
×
514
    }
515
}
516

517
@Component({
518
    selector: 'igx-circular-bar',
519
    templateUrl: 'templates/circular-bar.component.html',
520
    imports: [NgTemplateOutlet, NgClass]
521
})
522
export class IgxCircularProgressBarComponent extends BaseProgressDirective implements AfterViewInit, AfterContentInit {
2✔
523
    /**
524
     * @hidden
525
     */
526
    @HostBinding('class.igx-circular-bar')
UNCOV
527
    public cssClass = 'igx-circular-bar';
×
528

529
    /**
530
     * Sets the value of `id` attribute. If not provided it will be automatically generated.
531
     * ```html
532
     * <igx-circular-bar [id]="'igx-circular-bar-55'"></igx-circular-bar>
533
     * ```
534
     */
535
    @HostBinding('attr.id')
536
    @Input()
UNCOV
537
    public id = `igx-circular-bar-${NEXT_CIRCULAR_ID++}`;
×
538

539
    /**
540
     * @hidden
541
     */
542
    @HostBinding('class.igx-circular-bar--indeterminate')
543
    public get isIndeterminate() {
UNCOV
544
        return this.indeterminate;
×
545
    }
546

547
    /**
548
     * @hidden
549
     */
550
    @HostBinding('class.igx-circular-bar--animation-none')
551
    public get disableAnimationClass(): boolean {
UNCOV
552
        return !this._animate;
×
553
    }
554

555
    /**
556
     * @hidden
557
     */
558
    @HostBinding('class.igx-circular-bar--hide-counter')
559
    public get hasText(): boolean {
UNCOV
560
        return !!this.text;
×
561
    }
562

563
    /**
564
     * Sets the text visibility. By default, it is set to true.
565
     * ```html
566
     * <igx-circular-bar [textVisibility]="false"></igx-circular-bar>
567
     * ```
568
     */
569
    @Input({ transform: booleanAttribute })
UNCOV
570
    public textVisibility = true;
×
571

572
    @ContentChild(IgxProgressBarTextTemplateDirective, { read: IgxProgressBarTextTemplateDirective })
573
    public textTemplate: IgxProgressBarTextTemplateDirective;
574

575
    @ContentChild(IgxProgressBarGradientDirective, { read: IgxProgressBarGradientDirective })
576
    public gradientTemplate: IgxProgressBarGradientDirective;
577

578
    @ViewChild('circle', { static: true })
579
    private _svgCircle: ElementRef;
580

581
    /**
582
     * @hidden
583
     */
UNCOV
584
    public gradientId = `igx-circular-gradient-${NEXT_GRADIENT_ID++}`;
×
585

586
    /**
587
     * @hidden
588
     */
589
    public get context(): any {
UNCOV
590
        return {
×
591
            $implicit: { value: this.value, valueInPercent: this.valueInPercent, max: this.max }
592
        };
593
    }
594

595
    /**
596
     * @hidden
597
     */
598
    public get textContent(): string {
UNCOV
599
        return this.text;
×
600
    }
601

UNCOV
602
    constructor(private renderer: Renderer2) {
×
UNCOV
603
        super();
×
604
    }
605

606
    public ngAfterContentInit() {
UNCOV
607
        this._contentInit = true;
×
608
    }
609

610
    public ngAfterViewInit() {
UNCOV
611
        this.renderer.setStyle(
×
612
            this._svgCircle.nativeElement,
613
            'stroke',
614
            `url(#${this.gradientId})`
615
        );
616
    }
617
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc