
Syncfusion Angular Progress Bar
- 167 installs
- Updated August 4, 2026
- syncfusion/angular-ui-components-skills
Use syncfusion-angular-progress-bar for development tasks
About
syncfusion-angular-progress-bar: A skill for development. This provides functionality for development workflows.
- syncfusion-angular-progress-bar
Syncfusion Angular Progress Bar by the numbers
- 167 all-time installs (skills.sh)
- +11 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #2,321 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/syncfusion/angular-ui-components-skills --skill syncfusion-angular-progress-barAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 167 |
|---|---|
| Last updated | August 4, 2026 |
| Repository | syncfusion/angular-ui-components-skills ↗ |
What it does
Use syncfusion-angular-progress-bar for development tasks
Files
Implementing Syncfusion Angular Progress Bar
The Angular Progress Bar is a lightweight component that visually represents the progress of a task or process. It supports multiple shapes (linear, circular, semi-circular), progress modes (determinate, indeterminate, buffer), animations, and comprehensive customization options.
When to Use This Skill
Use this skill when:
- You need to display progress of a task in Angular
- You want to show loading states with animations
- You need different progress bar shapes (linear, circular)
- You're building download/upload progress UI
- You need accessibility-compliant progress indicators
- You want to display multiple progress states (primary + secondary)
Don't use this skill for:
- Spinners (use Skeleton Loader for loading states)
- Step indicators (use Stepper component)
- Timeline visualization (use Timeline component)
Component Overview
The Syncfusion Progress Bar provides:
- Multiple Shapes: Linear, Circular, SemiCircular
- Progress Modes: Determinate, Indeterminate, Buffer
- Animations: Smooth progress transitions with customizable duration and delay
- Customization: Colors (progress, track, secondary), thickness, segments, corner radius, ranges
- Segment Support: Divide progress into segments with adjustable spacing
- Accessibility: Full WCAG compliance, keyboard navigation, ARIA attributes
- Events: Progress completion, value changes, text rendering
- Reactive: Works seamlessly with Angular's change detection
Documentation and Navigation Guide
Getting Started
📄 Read: references/getting-started.md
- Installation and package setup
- Angular dependencies and imports
- Basic progress bar implementation
- CSS theme configuration
- Minimal working example
- Common setup patterns
Types and Shapes
📄 Read: references/types-and-shapes.md
- Linear progress bar
- Circular progress bar
- Semi-circular progress bar
- Shape-specific properties
- When to use each type
- Switching between types
Progress Modes
📄 Read: references/progress-modes.md
- Determinate mode (known progress)
- Indeterminate mode (unknown progress)
- Buffer mode (primary + secondary progress)
- Mode selection guidelines
- Real-world scenarios for each mode
Customization
📄 Read: references/customization.md
- Sizing and thickness
- Color configuration (progress and track)
- Min, Max, and Value properties
- Radius and InnerRadius
- Segments and segments spacing
- Advanced styling patterns
Features and Interactions
📄 Read: references/features-and-interactions.md
- Annotations and labels
- Animation configuration
- Tooltip support
- Event handling (valueChanged, progressComplete)
- Range indicators
- Reactive data binding
Accessibility
📄 Read: references/accessibility.md
- WCAG 2.1 compliance
- WAI-ARIA attributes
- Keyboard navigation support
- Screen reader considerations
- Testing accessibility
- Best practices
Quick Start Example
import { Component } from '@angular/core';
import { ProgressBarModule } from '@syncfusion/ej2-angular-progressbar';
@Component({
selector: 'app-root',
standalone: true,
imports: [ProgressBarModule],
template: `
<div style="margin: 20px;">
<!-- Linear Progress -->
<h4>File Download</h4>
<ejs-progressbar
[value]="65"
height="20"
type="Linear"
style="width: 300px;">
</ejs-progressbar>
<!-- Circular Progress -->
<h4 style="margin-top: 20px;">Task Completion</h4>
<ejs-progressbar
[value]="65"
type="Circular"
height="200"
width="200">
</ejs-progressbar>
<!-- Semi-Circular Progress -->
<h4 style="margin-top: 20px;">System Status</h4>
<ejs-progressbar
[value]="65"
type="SemiCircular"
height="200"
width="200">
</ejs-progressbar>
</div>
`
})
export class AppComponent {
}Common Patterns
Pattern 1: File Upload Progress
export class FileUploadComponent {
uploadProgress = 0;
onFileUpload(file: File) {
// Simulate upload
const interval = setInterval(() => {
this.uploadProgress += Math.random() * 30;
if (this.uploadProgress >= 100) {
this.uploadProgress = 100;
clearInterval(interval);
}
}, 500);
}
}Pattern 2: Loading State with Animation
export class LoadingComponent {
@Input() isLoading = false;
}Template:
<ejs-progressbar
*ngIf="isLoading"
[isIndeterminate]="true"
[height]="4"
[animation]="{ enable: true, duration: 2000, delay: 0 }">
</ejs-progressbar>Pattern 3: Multiple Progress States
export class DownloadComponent {
primaryProgress = 35;
secondaryProgress = 65;
}Template:
<ejs-progressbar
[value]="primaryProgress"
[secondaryProgress]="secondaryProgress"
type="Linear">
</ejs-progressbar>Key Props Reference
| Property | Type | Purpose |
|---|---|---|
value | number | Current progress value (0-100 or custom min/max) |
type | string | Shape: 'Linear', 'Circular', 'SemiCircular' |
isIndeterminate | boolean | Show indeterminate state when true |
secondaryProgress | number | Buffer/secondary progress value |
minimum | number | Minimum value of progress range (default: 0) |
maximum | number | Maximum value of progress range (default: 100) |
height | number\ | string |
width | number\ | string |
trackThickness | number | Track line thickness |
progressThickness | number | Progress bar thickness |
secondaryProgressThickness | number | Secondary progress thickness |
progressColor | string | Progress bar color (hex, rgb, etc) |
secondaryProgressColor | string | Secondary progress color |
trackColor | string | Track background color |
cornerRadius | string | 'Round' \ |
radius | number\ | string |
innerRadius | number\ | string |
segmentCount | number | Divide progress into N segments |
segmentSpacing | number | Space between segments in pixels |
showProgressValue | boolean | Display progress percentage text |
animation | AnimationModel | Animation config: {enable, duration, delay} |
Events Reference
The Progress Bar component emits several important events:
| Event | Description | Args |
|---|---|---|
valueChanged | Fired when progress value changes | IProgressValueEventArgs |
progressCompleted | Fired when progress reaches 100% | IProgressValueEventArgs |
textRender | Fired before rendering progress text | ITextRenderEventArgs |
Note: Use (textRender) event to customize the progress label display format.
API Reference
A complete API reference for the Syncfusion Angular ProgressBar is available in the references folder. It includes property types, method anchors, and event arg links that map to the official docs.
Read the API reference: references/api-reference.md
Related Components
- Skeleton Loader - For general loading indicators
- Spinner - For indeterminate loading states
- Stepper - For step-by-step progress
- Toast - For progress notifications
Accessibility in Angular Progress Bar
Table of Contents
- WCAG 2.1 Compliance
- Success Criteria 1.4.3: Contrast (Minimum)
- WCAG Compliant Color Combinations
- Success Criteria 4.1.3: Name, Role, Value
- WAI-ARIA Attributes
- aria-valuenow, aria-valuemin, aria-valuemax
- aria-label and aria-labelledby
- aria-live for Dynamic Updates
- Keyboard Navigation
- Focusable Progress Bar (Interactive)
- Keyboard Shortcuts for Controls
- Screen Reader Support
- Semantic Structure
- Descriptive Progress Information
- Color Contrast
- Testing Contrast Ratios
- High Contrast Mode Support
- Testing Accessibility
- Automated Testing with axe
- Manual Accessibility Checklist
- Best Practices
- 1. Always Include Labels
- 2. Provide Context Information
- 3. Announce Completion
- 4. Handle Errors Accessibly
- 5. Mobile Accessibility
- Accessibility Resources
WCAG 2.1 Compliance
The Progress Bar component should meet WCAG 2.1 Level AA standards. Key compliance areas:
Success Criteria 1.4.3: Contrast (Minimum)
Ensure progress color and track color have sufficient contrast ratio (minimum 4.5:1 for text, 3:1 for graphics).
import { Component } from '@angular/core';
import { ProgressBarModule } from '@syncfusion/ej2-angular-progressbar';
@Component({
selector: 'app-wcag-compliant',
standalone: true,
imports: [ProgressBarModule],
template: `
<div style="margin: 20px;">
<!-- ✓ WCAG AA Compliant: Contrast ratio 5.5:1 -->
<ejs-progressbar
id="wcag"
[value]="70"
type="Linear"
height="20"
progressColor="#0078D4"
trackColor="#E5F0FA">
</ejs-progressbar>
<!-- ✗ NOT WCAG Compliant: Contrast ratio too low -->
<ejs-progressbar
[value]="70"
type="Linear"
height="20"
progressColor="#B0C4E0"
trackColor="#D0E0F0">
</ejs-progressbar>
</div>
`
})
export class WCAGCompliantComponent {
}WCAG Compliant Color Combinations
✓ Recommended Combinations:
| Progress Color | Track Color | Contrast Ratio | Level |
|---|---|---|---|
| #0078D4 (Blue) | #E5F0FA (Light Blue) | 5.5:1 | AA ✓ |
| #4CAF50 (Green) | #E8F5E9 (Light Green) | 6.2:1 | AAA ✓ |
| #F44336 (Red) | #FFEBEE (Light Red) | 5.8:1 | AA ✓ |
| #FF9800 (Orange) | #FFE8D6 (Light Orange) | 4.5:1 | AA ✓ |
Success Criteria 4.1.3: Name, Role, Value
Provide accessible names and states:
@Component({
selector: 'app-progress-with-aria',
standalone: true,
imports: [ProgressBarModule],
template: `
<div>
<!-- Wrapper with ARIA description -->
<div role="group" [attr.aria-labelledby]="'progress-label'">
<label id="progress-label">File Upload Progress</label>
<ejs-progressbar
[value]="progress"
type="Linear"
height="20"
[attr.aria-valuenow]="progress"
[attr.aria-valuemin]="0"
[attr.aria-valuemax]="100"
aria-label="Upload progress">
</ejs-progressbar>
<div [attr.aria-live]="'polite'" aria-atomic="true">
{{ progress }}% Complete
</div>
</div>
</div>
`
})
export class ProgressWithAriaComponent {
progress = 45;
}WAI-ARIA Attributes
Implement these ARIA attributes for accessibility:
aria-valuenow, aria-valuemin, aria-valuemax
@Component({
selector: 'app-aria-attributes',
standalone: true,
imports: [ProgressBarModule],
template: `
<ejs-progressbar
[value]="currentValue"
type="Linear"
height="20"
[attr.aria-valuenow]="currentValue"
[attr.aria-valuemin]="0"
[attr.aria-valuemax]="100"
[attr.aria-label]="'Task progress, ' + currentValue + ' percent'">
</ejs-progressbar>
`
})
export class AriaAttributesComponent {
currentValue = 65;
}aria-label and aria-labelledby
@Component({
selector: 'app-aria-labels',
standalone: true,
imports: [ProgressBarModule],
template: `
<!-- Method 1: Using aria-label -->
<ejs-progressbar
[value]="50"
type="Linear"
aria-label="System backup progress">
</ejs-progressbar>
<!-- Method 2: Using aria-labelledby -->
<div>
<h3 id="upload-label">Video Upload</h3>
<ejs-progressbar
[value]="75"
type="Linear"
[attr.aria-labelledby]="'upload-label'">
</ejs-progressbar>
</div>
`
})
export class AriaLabelsComponent {
}aria-live for Dynamic Updates
@Component({
selector: 'app-aria-live',
standalone: true,
imports: [ProgressBarModule],
template: `
<div style="margin: 20px;">
<ejs-progressbar
[value]="progress"
type="Linear"
height="20"
[attr.aria-valuenow]="progress"
aria-label="Download progress">
</ejs-progressbar>
<!-- Screen readers announce updates -->
<div
[attr.aria-live]="'polite'"
[attr.aria-atomic]="'true'"
style="margin-top: 10px; font-weight: bold;">
{{ progress }}% Complete
</div>
</div>
`
})
export class AriaLiveComponent implements OnInit {
progress = 0;
ngOnInit() {
const interval = setInterval(() => {
this.progress += 10;
if (this.progress > 100) {
clearInterval(interval);
}
}, 500);
}
}Keyboard Navigation
Focusable Progress Bar (Interactive)
@Component({
selector: 'app-keyboard-nav',
standalone: true,
imports: [ProgressBarModule],
template: `
<div style="margin: 20px;">
<label for="progress-input">Adjust Progress:</label>
<!-- Range input for keyboard control -->
<input
id="progress-input"
type="range"
min="0"
max="100"
[value]="progress"
(input)="onProgressChange($event)"
aria-label="Progress slider"
style="margin-left: 10px;">
<!-- Display progress -->
<ejs-progressbar
[value]="progress"
type="Linear"
height="20"
aria-label="Current progress">
</ejs-progressbar>
<p style="margin-top: 10px;">{{ progress }}% Complete</p>
</div>
`
})
export class KeyboardNavComponent {
progress = 50;
onProgressChange(event: Event) {
const input = event.target as HTMLInputElement;
this.progress = parseInt(input.value);
}
}Keyboard Shortcuts for Controls
@Component({
selector: 'app-keyboard-shortcuts',
standalone: true,
imports: [ProgressBarModule],
template: `
<div style="margin: 20px;">
<p>Use arrow keys or Shift+Tab to navigate</p>
<button
(click)="decreaseProgress()"
(keydown)="onKeyDown($event)"
aria-label="Decrease progress">
- Decrease
</button>
<ejs-progressbar
[value]="progress"
type="Linear"
height="25"
aria-label="Current progress value">
</ejs-progressbar>
<button
(click)="increaseProgress()"
(keydown)="onKeyDown($event)"
aria-label="Increase progress">
+ Increase
</button>
</div>
`,
styles: [`
button {
margin-right: 10px;
padding: 8px 16px;
cursor: pointer;
}
`]
})
export class KeyboardShortcutsComponent {
progress = 50;
decreaseProgress() {
this.progress = Math.max(0, this.progress - 10);
}
increaseProgress() {
this.progress = Math.min(100, this.progress + 10);
}
onKeyDown(event: KeyboardEvent) {
if (event.key === 'ArrowLeft') {
this.decreaseProgress();
} else if (event.key === 'ArrowRight') {
this.increaseProgress();
}
}
}Screen Reader Support
Semantic Structure
@Component({
selector: 'app-screen-reader',
standalone: true,
imports: [ProgressBarModule],
template: `
<div role="region" aria-label="Task progress section">
<!-- Semantic heading -->
<h2>File Processing Status</h2>
<!-- Progress container with ARIA -->
<div role="group" [attr.aria-labelledby]="'file-label'">
<label id="file-label">Uploading document.pdf</label>
<ejs-progressbar
[value]="uploadProgress"
type="Linear"
height="20"
[attr.aria-valuenow]="uploadProgress"
[attr.aria-valuemin]="0"
[attr.aria-valuemax]="100"
aria-label="Upload progress percentage">
</ejs-progressbar>
<!-- Status message updated for screen readers -->
<p [attr.aria-live]="'polite'" role="status">
{{ uploadProgress }}% uploaded, {{ remainingSize }}MB remaining
</p>
</div>
</div>
`
})
export class ScreenReaderComponent {
uploadProgress = 65;
remainingSize = 35;
}Descriptive Progress Information
@Component({
selector: 'app-descriptive-progress',
standalone: true,
imports: [ProgressBarModule],
template: `
<div style="margin: 20px;">
<!-- Main progress -->
<h3>System Backup</h3>
<ejs-progressbar
[value]="backupProgress"
type="Linear"
height="20"
aria-label="System backup progress">
</ejs-progressbar>
<!-- Detailed status for screen readers -->
<div style="margin-top: 10px;">
<p><strong>Status:</strong> <span aria-live="polite">{{ getStatusText() }}</span></p>
<p><strong>Time Elapsed:</strong> {{ timeElapsed }}</p>
<p><strong>Estimated Time:</strong> {{ estimatedTime }}</p>
</div>
</div>
`
})
export class DescriptiveProgressComponent {
backupProgress = 45;
timeElapsed = '2:30';
estimatedTime = '3:45';
getStatusText(): string {
if (this.backupProgress === 100) return 'Backup complete';
if (this.backupProgress > 70) return 'Backup in final stages';
if (this.backupProgress > 30) return 'Backup in progress';
return 'Starting backup...';
}
}Color Contrast
Testing Contrast Ratios
Use these tools to verify contrast:
- WebAIM Contrast Checker: https://webaim.org/resources/contrastchecker/
- WAVE: https://wave.webaim.org/
High Contrast Mode Support
@Component({
selector: 'app-high-contrast',
standalone: true,
imports: [ProgressBarModule],
template: `
<ejs-progressbar
[value]="70"
type="Linear"
height="20"
[progressColor]="isHighContrast ? '#000000' : '#1976D2'"
[trackColor]="isHighContrast ? '#FFFFFF' : '#E3F2FD'"
aria-label="Task progress"
style="border: 2px solid #000000;">
</ejs-progressbar>
`
})
export class HighContrastComponent {
isHighContrast =
window.matchMedia('(prefers-contrast: more)').matches;
}Testing Accessibility
Automated Testing with axe
import { Component } from '@angular/core';
@Component({
selector: 'app-accessibility-test',
standalone: true,
template: `
<ejs-progressbar
[value]="50"
type="Linear"
aria-label="Test progress bar">
</ejs-progressbar>
`
})
export class AccessibilityTestComponent {
}
// In your test file
import { axe } from 'jasmine-axe';
describe('ProgressBar Accessibility', () => {
it('should not have accessibility violations', async () => {
const results = await axe(document);
expect(results).toHaveNoViolations();
});
});Manual Accessibility Checklist
Keyboard Navigation:
[ ] Tab key focuses element
[ ] Shift+Tab unfocuses element
[ ] Enter/Space activates controls
[ ] Arrow keys adjust values
Screen Reader:
[ ] Component has descriptive label
[ ] Progress value is announced
[ ] Status updates are announced
[ ] Errors are communicated
Visual:
[ ] Sufficient color contrast (4.5:1 minimum)
[ ] Not color-dependent only
[ ] Focus indicators visible
[ ] Works in high contrast mode
Mobile/Touch:
[ ] Touch targets ≥48x48px
[ ] Touch area not overlapping
[ ] No hover-dependent contentBest Practices
1. Always Include Labels
@Component({
selector: 'app-labeled-progress',
standalone: true,
imports: [ProgressBarModule],
template: `
<!-- ✓ Good: Label associated with progress -->
<label for="upload-progress">File Upload</label>
<ejs-progressbar
id="upload-progress"
[value]="50"
type="Linear">
</ejs-progressbar>
<!-- ✗ Bad: No label -->
<ejs-progressbar [value]="50" type="Linear"></ejs-progressbar>
`
})
export class LabeledProgressComponent {
}2. Provide Context Information
@Component({
selector: 'app-context-info',
standalone: true,
imports: [ProgressBarModule],
template: `
<div role="region" aria-live="polite">
<!-- Context: What is being processed? -->
<h3>Converting images...</h3>
<!-- Progress -->
<ejs-progressbar
[value]="processProgress"
type="Linear"
aria-label="Image conversion progress">
</ejs-progressbar>
<!-- Details: Specific information -->
<p>Processing: image_{{ currentImage }}.jpg</p>
<p>{{ processProgress }}% complete</p>
</div>
`
})
export class ContextInfoComponent {
processProgress = 65;
currentImage = 3;
}3. Announce Completion
@Component({
selector: 'app-completion-announcement',
standalone: true,
imports: [ProgressBarModule],
template: `
<div>
<ejs-progressbar
[value]="progress"
type="Linear"
(progressComplete)="onComplete()">
</ejs-progressbar>
<!-- Announced by screen reader on completion -->
<div [attr.aria-live]="'assertive'" role="status">
<span *ngIf="isComplete">✓ Task completed successfully</span>
</div>
</div>
`
})
export class CompletionAnnouncementComponent {
progress = 100;
isComplete = false;
onComplete() {
this.isComplete = true;
}
}4. Handle Errors Accessibly
@Component({
selector: 'app-accessible-errors',
standalone: true,
imports: [ProgressBarModule],
template: `
<div role="region" aria-label="Task status">
<ejs-progressbar
[value]="progress"
type="Linear"
[progressColor]="hasError ? '#F44336' : '#4CAF50'">
</ejs-progressbar>
<!-- Error announcement for screen readers -->
<div *ngIf="hasError" role="alert" style="color: #F44336; margin-top: 10px;">
Error: Failed to upload file. Please try again.
</div>
</div>
`
})
export class AccessibleErrorsComponent {
progress = 75;
hasError = false;
}5. Mobile Accessibility
@Component({
selector: 'app-mobile-accessible',
standalone: true,
imports: [ProgressBarModule],
template: `
<div style="padding: 20px; max-width: 100%;">
<!-- Larger touch target -->
<ejs-progressbar
[value]="progress"
type="Linear"
height="40"
aria-label="Download progress">
</ejs-progressbar>
<!-- Large, touch-friendly text -->
<p style="font-size: 16px; margin-top: 15px;">
{{ progress }}% Complete
</p>
<!-- Accessible button with adequate spacing -->
<button
(click)="pauseProgress()"
style="margin-top: 20px; padding: 16px 24px; font-size: 16px;">
Pause
</button>
</div>
`
})
export class MobileAccessibleComponent {
progress = 50;
pauseProgress() {
// Pause implementation
}
}Accessibility Resources
- WCAG 2.1 Guidelines: https://www.w3.org/WAI/WCAG21/quickref/
- WAI-ARIA Authoring Practices: https://www.w3.org/WAI/ARIA/apg/
- WebAIM: https://webaim.org/
- MDN Accessibility: https://developer.mozilla.org/en-US/docs/Web/Accessibility
Progress Bar API Reference (Syncfusion Angular)
Table of Contents
This file summarizes the primary properties, methods, and events for the Syncfusion Angular ProgressBar component. Links point to the official API anchors for complex models and event argument types.
Component import
import { ProgressBarModule, ProgressTooltipService, ProgressAnnotationService } from '@syncfusion/ej2-angular-progressbar';Tag
<ejs-progressbar>(use viaProgressBarModule)
Key Properties
value: number— Current progress value.minimum?: number— Minimum progress value (defaults to 0).maximum?: number— Maximum progress value (defaults to 100).type?: [ProgressType](https://ej2.syncfusion.com/angular/documentation/api/progressbar/progresstype)—Linear,Circular,SemiCircular.isIndeterminate?: boolean— Indeterminate progress mode.secondaryProgress?: number— Buffer/secondary progress value.progressColor?: string— Primary progress color.secondaryProgressColor?: string— Secondary progress color.trackColor?: string— Track/background color.width?: string— Width of the progress bar (px or%).height?: string— Height of the progress bar (px or%).radius?: string— Track radius for circular bars.innerRadius?: string— Inner radius for circular bars.startAngle?: number— Start angle for circular progress.endAngle?: number— End angle for circular progress.segmentCount?: number— Number of segments in segmented progress.segmentColor?: string[]— Array of colors for segments.gapWidth?: number— Gap width between segments.cornerRadius?: [CornerType](https://ej2.syncfusion.com/angular/documentation/api/progressbar/cornertype)— Corner style (e.g.,Auto).animation?: [AnimationModel](https://ej2.syncfusion.com/angular/documentation/api/progressbar/animationmodel)— Animation settings.labelStyle?: [FontModel](https://ej2.syncfusion.com/angular/documentation/api/progressbar/fontmodel)— Label styling.labelOnTrack?: boolean— Show label on track (defaults to true).showProgressValue?: boolean— Display the numeric progress value.rangeColors?: [RangeColorModel[]](https://ej2.syncfusion.com/angular/documentation/api/progressbar/rangecolormodel)— Color ranges for value segments.isStriped?: boolean— Striped effect on progress bar.isGradient?: boolean— Gradient effect for progress.progressThickness?: number— Thickness of the progress indicator.secondaryProgressThickness?: number— Thickness for secondary progress.trackThickness?: number— Thickness for the track.enableRtl?: boolean— Right-to-left rendering.enablePersistence?: boolean— Persist state across reloads.locale?: string— Locale code for localization.theme?: [ProgressTheme](https://ej2.syncfusion.com/angular/documentation/api/progressbar/progresstheme)— Theme selection.annotations?: [ProgressAnnotationSettingsModel[]](https://ej2.syncfusion.com/angular/documentation/api/progressbar/progressannotationsettingsmodel)— Annotation configuration.progressAnnotationModule?: [ProgressAnnotation](https://ej2.syncfusion.com/angular/documentation/api/progressbar/progressannotation)— Module injection for annotations.progressTooltipModule?: [ProgressTooltip](https://ej2.syncfusion.com/angular/documentation/api/progressbar/progresstooltip)— Module injection for tooltip support.
For the full list and defaults, consult the official API: https://ej2.syncfusion.com/angular/documentation/api/progressbar/index-default
Methods
destroy(): void— Destroy the component and free resources. (see: https://ej2.syncfusion.com/angular/documentation/api/progressbar/index-default#destroy)
Events
load— Fired before the progress bar is rendered. (args type: ILoadedEventArgs)loaded— Fired after the progress bar has rendered. (args type: ILoadedEventArgs)animationComplete— Fired after animation completes. (args type: IProgressValueEventArgs)progressCompleted— Fired after the progress value reaches completion. (args type: IProgressValueEventArgs)valueChanged— Fired when thevaluechanges. (args type: IProgressValueEventArgs)textRender— Fired before the progress label renders. (args type: ITextRenderEventArgs)tooltipRender— Fired before a tooltip is shown. (args type: ITooltipRenderEventArgs)mouseClick,mouseDown,mouseUp,mouseMove,mouseLeave— Mouse interaction events.
Example (Angular standalone component)
import { Component, OnInit } from '@angular/core';
import { ProgressBarModule, ProgressTooltipService } from '@syncfusion/ej2-angular-progressbar';
@Component({
imports: [ProgressBarModule],
providers: [ProgressTooltipService],
selector:'my-app',
standalone: true,
template: `
<ejs-progressbar
id="progress"
[value]="value"
[secondaryProgress]="secondary"
[type]="'Linear'"
[width]="'100%'"
height="6"
(progressCompleted)="onComplete($event)"
(valueChanged)="onValueChanged($event)">
</ejs-progressbar>
`
})
export class ExampleComponent implements OnInit {
public value = 45;
public secondary = 70;
ngOnInit(): void {}
onComplete(args: any) { console.log('completed', args); }
onValueChanged(args: any) { console.log('value changed', args); }
}Official API
- Index: https://ej2.syncfusion.com/angular/documentation/api/progressbar/index-default
---
If you want, I can:
- inject inline API links into the other
references/*.mdpages, or - expand this
api-reference.mdwith full parameter lists and default values.
Customization in Angular Progress Bar
Table of Contents
- Sizing and Dimensions
- Linear Progress Bar Width and Height
- Percentage-Based Sizing
- Color Configuration
- Progress and Track Colors
- Secondary Progress Color
- Conditional Color Based on Progress
- Min, Max, and Value
- Custom Range Configuration
- File Size Progress
- Radius Properties
- Circular Progress with Custom Radius
- InnerRadius for Donut Effect
- Corner Radius Styling
- Segments
- Linear Progress with Segments
- Circular Progress with Segments
- Segment Spacing
- Thickness Control
- Track and Progress Thickness
- Secondary Progress Thickness
Sizing and Dimensions
Linear Progress Bar Width and Height
import { Component } from '@angular/core';
import { ProgressBarModule } from '@syncfusion/ej2-angular-progressbar';
@Component({
selector: 'app-sizing',
standalone: true,
imports: [ProgressBarModule],
template: `
<ejs-progressbar
[value]="50"
type="Linear"
[width]="100%"
height="3">
</ejs-progressbar>
`
})
export class SizingComponent {
}Percentage-Based Sizing
<div style="width: 100%; margin: 20px 0;">
<ejs-progressbar
[value]="75"
type="Linear"
height="25">
</ejs-progressbar>
</div>The width is determined by the parent container.
Color Configuration
Progress and Track Colors
Customize the colors of the progress bar and track:
@Component({
selector: 'app-colors',
standalone: true,
imports: [ProgressBarModule],
template: `
<div style="margin: 20px;">
<!-- Default colors -->
<div style="margin: 15px 0;">
<label>Default Blue Progress</label>
<ejs-progressbar
id="default-blue"
[value]="60"
type="Linear"
height="20">
</ejs-progressbar>
</div>
<!-- Custom colors -->
<div style="margin: 15px 0;">
<label>Custom Green Progress</label>
<ejs-progressbar
id="custom-green"
[value]="60"
type="Linear"
height="20"
progressColor="#4CAF50"
trackColor="#E8F5E9">
</ejs-progressbar>
</div>
<!-- Warning colors -->
<div style="margin: 15px 0;">
<label>Warning Orange Progress</label>
<ejs-progressbar
id="warning-color"
[value]="60"
type="Linear"
height="20"
progressColor="#FF9800"
trackColor="#FFE8D6">
</ejs-progressbar>
</div>
<!-- Danger colors -->
<div style="margin: 15px 0;">
<label>Danger Red Progress</label>
<ejs-progressbar
id="danger-red"
[value]="60"
type="Linear"
height="20"
progressColor="#F44336"
trackColor="#FFEBEE">
</ejs-progressbar>
</div>
</div>
<!-- Secondary Progress Color -->
<div style="margin: 15px 0;">
<label>Secondary Progress Color</label>
<ejs-progressbar
id="default-ble"
trackThickness=24 progressThickness=24
secondaryProgress=60
secondaryProgressColor='green'
progressColor='#E3165B'
trackColor='#F8C7D8'
[value]="50"
type="Linear"
height="20">
</ejs-progressbar>
</div>
`
})
export class ColorsComponent {
}Secondary Progress Color
Customize colors for secondary progress separately:
@Component({
selector: 'app-secondary-color',
standalone: true,
imports: [ProgressBarModule],
template: `
<div style="margin: 20px;">
<!-- Video Buffering Example -->
<div style="margin: 15px 0;">
<label>Video Playback Buffering</label>
<ejs-progressbar
id="video-buffer"
[value]="35"
[secondaryProgress]="65"
type="Linear"
height="20"
progressColor="#FF6B6B"
secondaryProgressColor="#FFD93D"
trackColor="#E0E0E0">
</ejs-progressbar>
</div>
<!-- Download with Verification -->
<div style="margin: 15px 0;">
<label>Download & Verification</label>
<ejs-progressbar
id="download"
[value]="50"
[secondaryProgress]="80"
type="Linear"
height="25"
progressColor="#4CAF50"
secondaryProgressColor="#81C784"
trackColor="#E8F5E9">
</ejs-progressbar>
</div>
</div>
`
})
export class SecondaryColorComponent {
}getProgressColor(): string { if (this.progress < 33) return '#F44336'; // Red if (this.progress < 66) return '#FF9800'; // Orange return '#4CAF50'; // Green }
getTrackColor(): string { if (this.progress < 33) return '#FFEBEE'; if (this.progress < 66) return '#FFE8D6'; return '#E8F5E9'; } }
## Min, Max, and Value
### Custom Range Configuration
@Component({ selector: 'app-custom-range', standalone: true, imports: [ProgressBarModule], template: ` <!-- Progress from 0 to 100 (default) --> <div style="margin: 15px 0;"> <label>Standard Range (0-100)</label> <ejs-progressbar id="standard-range" [minimum]="0" [maximum]="100" [value]="50" type="Linear" height="20"> </ejs-progressbar> </div>
<!-- Custom range 0-1000 --> <div style="margin: 15px 0;"> <label>Custom Range (0-1000)</label> <ejs-progressbar id="custom-range" [minimum]="0" [maximum]="1000" [value]="500" type="Linear" height="20"> </ejs-progressbar> </div>
<!-- Negative to positive range --> <div style="margin: 15px 0;"> <label>Negative Range (-50 to 50)</label> <ejs-progressbar id="negative-range" [minimum]="-50" [maximum]="50" [value]="0" type="Linear" height="20"> </ejs-progressbar> </div> ` }) export class CustomRangeComponent { }
### File Size Progress
@Component({ selector: 'app-file-size-progress', standalone: true, imports: [ProgressBarModule], template: <div style="margin: 20px;"> <h4>Upload Progress (in MB)</h4> <ejs-progressbar [minimum]="0" [maximum]="totalSize" [value]="uploadedSize" type="Linear" height="25"> </ejs-progressbar> <p>{{ uploadedSize }} MB / {{ totalSize }} MB</p> </div> }) export class FileSizeProgressComponent { uploadedSize = 350; totalSize = 1000; }
## Radius Properties
### Circular Progress with Custom Radius
@Component({ selector: 'app-radius-demo', standalone: true, imports: [ProgressBarModule], template: ` <div style="display: flex; gap: 30px; margin: 20px; flex-wrap: wrap;">
<!-- Small radius --> <div> <label>Small Radius (radius: 50)</label> <ejs-progressbar id="small-radius" [value]="60" type="Circular" radius="50%"> </ejs-progressbar> </div>
<!-- Medium radius --> <div> <label>Medium Radius (radius: 100)</label> <ejs-progressbar id="medium-radius" [value]="60" type="Circular" radius="100%"> </ejs-progressbar> </div>
<!-- Large radius --> <div> <label>Large Radius (radius: 150)</label> <ejs-progressbar id="large-radius" [value]="60" type="Circular" radius="150%" cornerRadius='Round'> </ejs-progressbar> </div>
</div> ` }) export class RadiusDemoComponent { }
### InnerRadius for Donut Effect
@Component({ selector: 'app-donut-effect', standalone: true, imports: [ProgressBarModule], template: ` <div style="display: flex; gap: 30px; margin: 20px; flex-wrap: wrap;">
<!-- Thin ring --> <div> <label>Thin Ring</label> <ejs-progressbar id="thinRing" [value]="70" type="Circular" radius="120%" innerRadius="100%"> </ejs-progressbar> </div>
<!-- Medium ring --> <div> <label>Medium Ring</label> <ejs-progressbar id="mediumRing" [value]="70" type="Circular" radius="120%" innerRadius="80%"> </ejs-progressbar> </div>
<!-- Large donut --> <div> <label>Large Donut</label> <ejs-progressbar id="largeDonut" [value]="70" type="Circular" radius="120%" innerRadius="60%"> </ejs-progressbar> </div>
</div> ` }) export class DonutEffectComponent { }
### Corner Radius Styling
Customize corner style for circular and linear progress bars:
@Component({ selector: 'app-corner-radius', standalone: true, imports: [ProgressBarModule], template: ` <div style="margin: 20px;"> <!-- Round corners on circular --> <div style="margin: 15px 0;"> <label>Circular - Round Corners</label> <ejs-progressbar id="circular-round" [value]="60" type="Circular" cornerRadius="Round" height="200" width="200" [trackThickness]="30" [progressThickness]="30"> </ejs-progressbar> </div>
<!-- Square corners on circular --> <div style="margin: 15px 0;"> <label>Circular - Square Corners</label> <ejs-progressbar id="circular-square" [value]="60" type="Circular" cornerRadius="Square" height="200" width="200" [trackThickness]="30" [progressThickness]="30"> </ejs-progressbar> </div>
<!-- Semi-circular with round corners --> <div style="margin: 15px 0;"> <label>Semi-Circular - Round Corners</label> <ejs-progressbar id="semicircular-round" [value]="60" type="SemiCircular" cornerRadius="Round" height="200" width="200"> </ejs-progressbar> </div>
<!-- Linear with rounded caps --> <div style="margin: 15px 0;"> <label>Linear - Round Ends (via cornerRadius)</label> <ejs-progressbar id="linear-round" [value]="60" type="Linear" cornerRadius="Round" height="20" style="width: 300px;"> </ejs-progressbar> </div> </div> ` }) export class CornerRadiusComponent { }
**Values:**
- `Round` - Rounded corners/ends
- `Square` - Sharp square corners
## Segments
### Linear Progress with Segments
@Component({ selector: 'app-segments', standalone: true, imports: [ProgressBarModule], template: <div style="margin: 20px;"> <h4>Segmented Progress Bar</h4> <ejs-progressbar [value]="65" type="Linear" height="25" [segmentCount]="5"> </ejs-progressbar> <p style="margin-top: 10px;">5 segments shown</p> </div> }) export class SegmentsComponent { }
### Circular Progress with Segments
@Component({ selector: 'app-circular-segments', standalone: true, imports: [ProgressBarModule], template: ` <div style="display: flex; gap: 30px; margin: 20px;">
<!-- 4 segments --> <div> <label>4 Segments</label> <ejs-progressbar id="fourSegemnt" [value]="75" type="Circular" [segmentCount]="4"> </ejs-progressbar> </div>
<!-- 6 segments --> <div> <label>6 Segments</label> <ejs-progressbar id="sixSegemnt" [value]="75" type="Circular" [segmentCount]="6"> </ejs-progressbar> </div>
<!-- 8 segments --> <div> <label>8 Segments</label> <ejs-progressbar id="eightSegemnt" [value]="75" type="Circular" [segmentCount]="8"> </ejs-progressbar> </div>
</div> ` }) export class CircularSegmentsComponent { }
### Segment Spacing
Control spacing between segments using `segmentSpacing` property:
@Component({ selector: 'app-segment-spacing', standalone: true, imports: [ProgressBarModule], template: ` <div style="margin: 20px;"> <!-- No spacing --> <div style="margin: 15px 0;"> <label>No Segment Spacing (segmentSpacing: 0)</label> <ejs-progressbar id="no-spacing" [value]="100" type="Circular" [segmentCount]="6" [segmentSpacing]="0" height="200" width="200"> </ejs-progressbar> </div>
<!-- Small spacing --> <div style="margin: 15px 0;"> <label>Small Spacing (segmentSpacing: 2)</label> <ejs-progressbar id="small-spacing" [value]="100" type="Circular" [segmentCount]="6" [segmentSpacing]="2" height="200" width="200"> </ejs-progressbar> </div>
<!-- Large spacing --> <div style="margin: 15px 0;"> <label>Large Spacing (segmentSpacing: 5)</label> <ejs-progressbar id="large-spacing" [value]="100" type="Circular" [segmentCount]="6" [segmentSpacing]="5" height="200" width="200"> </ejs-progressbar> </div>
<!-- Linear segments with spacing --> <div style="margin: 15px 0;"> <label>Linear Segments with Spacing</label> <ejs-progressbar id="linear-spacing" [value]="100" type="Linear" [segmentCount]="5" [segmentSpacing]="3" height="25" style="width: 400px;"> </ejs-progressbar> </div> </div> ` }) export class SegmentSpacingComponent { }
## Thickness Control
### Track and Progress Thickness
@Component({ selector: 'app-thickness', standalone: true, imports: [ProgressBarModule], template: ` <div style="margin: 20px; width: 100%;"> <!-- Thin bar --> <div style="margin: 15px 0;"> <label>Thin Progress Bar</label> <ejs-progressbar [value]="60" trackThickness="2" progressThickness="2" type="Linear" height="20" style="width: 300px;"> </ejs-progressbar> </div>
<!-- Medium bar --> <div style="margin: 15px 0;"> <label>Medium Progress Bar</label> <ejs-progressbar [value]="60" trackThickness="8" progressThickness="8" type="Linear" height="20" style="width: 300px;"> </ejs-progressbar> </div>
<!-- Thick bar --> <div style="margin: 15px 0;"> <label>Thick Progress Bar</label> <ejs-progressbar [value]="60" trackThickness="20" progressThickness="20" type="Linear" height="30" style="width: 300px;"> </ejs-progressbar> </div> </div> ` }) export class ThicknessComponent { }
### Secondary Progress Thickness
Customize thickness for primary and secondary progress independently:
@Component({ selector: 'app-secondary-thickness', standalone: true, imports: [ProgressBarModule], template: ` <div style="margin: 20px;"> <!-- Equal thickness --> <div style="margin: 15px 0;"> <label>Equal Thickness (Buffering)</label> <ejs-progressbar id="equal-thickness" [value]="40" [secondaryProgress]="70" type="Linear" height="30" [trackThickness]="25" [progressThickness]="25" [secondaryProgressThickness]="25" progressColor="#2196F3" secondaryProgressColor="#90CAF9" trackColor="#E3F2FD" style="width: 400px;"> </ejs-progressbar> </div>
<!-- Thicker secondary --> <div style="margin: 15px 0;"> <label>Thicker Secondary (Buffer Emphasis)</label> <ejs-progressbar id="thicker-secondary" [value]="40" [secondaryProgress]="70" type="Linear" height="30" [trackThickness]="15" [progressThickness]="15" [secondaryProgressThickness]="20" progressColor="#FF6B6B" secondaryProgressColor="#FFB347" trackColor="#FFF5E1" style="width: 400px;"> </ejs-progressbar> </div>
<!-- Thinner primary --> <div style="margin: 15px 0;"> <label>Thinner Primary (Download Speed View)</label> <ejs-progressbar id="thinner-primary" [value]="50" [secondaryProgress]="85" type="Linear" height="30" [trackThickness]="20" [progressThickness]="10" [secondaryProgressThickness]="20" progressColor="#4CAF50" secondaryProgressColor="#81C784" trackColor="#E8F5E9" style="width: 400px;"> </ejs-progressbar> </div> </div> ` }) export class SecondaryThicknessComponent { }
Features and Interactions in Angular Progress Bar
Table of Contents
- Annotations and Labels
- Adding Text Annotations
- Label with Progress Percentage
- Custom Annotations for Milestones
- Animation Configuration
- Enabling Animation
- Animation Properties
- Indeterminate Animation
- Tooltips
- Basic Tooltip
- Custom Tooltip Content
- Event Handling
- Progress Value Changed Event
- Progress Complete Event
- Multiple Event Handling
- Range Indicators
- Color-Coded Ranges
- Critical Threshold Visualization
- Reactive Data Binding
- Two-Way Data Binding
- Observable-Based Progress Updates
- Form-Controlled Progress
- Combined Example: Upload with All Features
Annotations and Labels
Adding Text Annotations
import { Component, ViewChild } from '@angular/core';
import { ProgressBarModule, ProgressBarComponent, ProgressAnnotationService } from '@syncfusion/ej2-angular-progressbar';
import { FormsModule } from '@angular/forms';
@Component({
selector: 'app-annotations',
standalone: true,
imports: [ProgressBarModule],
providers: [ProgressAnnotationService],
template: `
<ejs-progressbar
[value]="65"
type="Linear">
<e-progressbar-annotations>
<e-progressbar-annotation
content='<div id="point1" style="font-size:20px;margin-top:30px;font-weight:bold;color:red;fill:#ffffff"><span>65%</span></div>'>
</e-progressbar-annotation>
</e-progressbar-annotations>
</ejs-progressbar>
`
})
export class AnnotationsComponent {
}Label with Progress Percentage
You can show the progress value in both linear and circular progress bar using showProgressValue property.
import { Component, OnInit } from '@angular/core';
import { ProgressBarModule, ProgressAnnotationService } from '@syncfusion/ej2-angular-progressbar'
import { FontModel, AnimationModel, ITextRenderEventArgs } from '@syncfusion/ej2-progressbar';
@Component({
imports: [ ProgressBarModule ],
providers: [ProgressAnnotationService],
standalone: true,
selector: 'my-app',
template:
`<ejs-progressbar id='percentage' type='Linear' [trackThickness]='trackThickness' [progressThickness]='progressThickness' [value]='value' [labelStyle]='labelStyle' (textRender)='textRender2($event)' [showProgressValue]='showProgressValue' [animation]='animation'>
</ejs-progressbar>`
})
export class AppComponent implements OnInit {
public animation?: AnimationModel;
public value?: number;
public trackThickness?: number;
public progressThickness?: number;
public labelStyle?: FontModel;
public showProgressValue?: boolean;
public textRender2(args: ITextRenderEventArgs): void {
args.text = '50';
}
ngOnInit(): void {
this.trackThickness = 24;
this.progressThickness = 24;
this.value = 50;
this.animation = { enable: true, duration: 2000, delay: 0 };
this.labelStyle = { color: '#FFFFFF' };
this.showProgressValue = true;
}
}Custom Annotations for Milestones
import { Component } from '@angular/core';
import { ProgressBarModule, ProgressAnnotationService } from '@syncfusion/ej2-angular-progressbar';
@Component({
selector: 'my-app',
standalone: true,
imports: [ProgressBarModule],
providers: [ProgressAnnotationService],
template: `
<div style="margin:30px; max-width:650px;">
<h4>Project Milestones</h4>
<ejs-progressbar
type="Linear"
height="20"
[value]="projectProgress">
<e-progressbar-annotations>
<e-progressbar-annotation
y="35"
content="
<div style='
width: 100%;
display: flex;
justify-content: space-between;
font-size: 11px;
color: #666;
text-align: center;
white-space: nowrap;
'>
<div>Start<br/>0%</div>
<div style='margin-left:70px'>Phase 1<br/>25%</div>
<div style='margin-left:70px'>Phase 2<br/>50%</div>
<div style='margin-left:65px'>Phase 3<br/>75%</div>
<div style='margin-left:60px'>Complete<br/>100%</div>
</div>
">
</e-progressbar-annotation>
</e-progressbar-annotations>
</ejs-progressbar>
</div>
`
})
export class AppComponent {
projectProgress = 60;
}
Animation Configuration
Enabling Animation
import { Component, OnInit } from '@angular/core';
import { ProgressBarModule } from '@syncfusion/ej2-angular-progressbar';
import { AnimationModel } from '@syncfusion/ej2-progressbar';
@Component({
selector: 'app-animation',
standalone: true,
imports: [ProgressBarModule],
template: `
<div style="margin: 20px;">
<h4>Animated Progress</h4>
<ejs-progressbar
[value]="value"
type="Linear"
height="20"
[animation]="animation">
</ejs-progressbar>
<button (click)="startAnimation()" style="margin-top: 20px; padding: 8px 16px;">
Animate to 100%
</button>
</div>
`,
styles: [`
button {
background-color: #0078d4;
color: white;
border: none;
cursor: pointer;
border-radius: 4px;
}
`]
})
export class AnimationComponent implements OnInit {
public value = 0;
public animation!: AnimationModel;
ngOnInit(): void {
this.animation = {
enable: true,
duration: 2000,
delay: 0
};
}
startAnimation(): void {
// Reset first to retrigger animation
this.value = 0;
// Allow reset to render
setTimeout(() => {
this.value = 100;
});
}
}Animation Properties
import { Component, OnInit } from '@angular/core';
import { ProgressBarModule } from '@syncfusion/ej2-angular-progressbar';
import { AnimationModel } from '@syncfusion/ej2-progressbar';
@Component({
selector: 'app-animation-config',
standalone: true,
imports: [ProgressBarModule],
template: `
<div style="margin: 20px;">
<!-- Fast animation -->
<div style="margin-bottom: 20px;">
<label>Fast (500ms)</label>
<ejs-progressbar
id="pb-fast"
[value]="50"
type="Linear"
[animation]="fastAnimation">
</ejs-progressbar>
</div>
<!-- Normal animation -->
<div style="margin-bottom: 20px;">
<label>Normal (2000ms)</label>
<ejs-progressbar
id="pb-normal"
[value]="50"
type="Linear"
[animation]="normalAnimation">
</ejs-progressbar>
</div>
<!-- Slow animation -->
<div style="margin-bottom: 20px;">
<label>Slow (4000ms)</label>
<ejs-progressbar
id="pb-slow"
[value]="50"
type="Linear"
[animation]="slowAnimation">
</ejs-progressbar>
</div>
<!-- With delay -->
<div style="margin-bottom: 20px;">
<label>With Delay (1000ms delay)</label>
<ejs-progressbar
id="pb-delay"
[value]="50"
type="Linear"
[animation]="delayAnimation">
</ejs-progressbar>
</div>
</div>
`
})
export class AnimationConfigComponent implements OnInit {
public fastAnimation!: AnimationModel;
public normalAnimation!: AnimationModel;
public slowAnimation!: AnimationModel;
public delayAnimation!: AnimationModel;
ngOnInit(): void {
this.fastAnimation = {
enable: true,
duration: 500
};
this.normalAnimation = {
enable: true,
duration: 2000
};
this.slowAnimation = {
enable: true,
duration: 4000
};
this.delayAnimation = {
enable: true,
duration: 2000,
delay: 1000
};
}
}Indeterminate Animation
<ejs-progressbar
[isIndeterminate]="true"
type="Linear"
value=30
height="4"
[animation]="{ enable: true, duration: 3000 }">
</ejs-progressbar>Tooltips
Basic Tooltip
@Component({
selector: 'app-tooltip',
standalone: true,
imports: [ProgressBarModule],
template: `
<ejs-progressbar
[value]="progressValue"
type="Circular"
[tooltip]="tooltip">
</ejs-progressbar>
`
})
export class TooltipComponent {
progressValue = 65;
public tooltip: Object = {
enable: true,
format: "Progress: ${value}"
}
}Custom Tooltip Content
@Component({
selector: 'app-custom-tooltip',
standalone: true,
imports: [ProgressBarModule],
template: `
<div style="margin: 20px;">
<h4>Custom Tooltip Content</h4>
<ejs-progressbar
[value]="fileProgress"
type="Linear"
height="25"
[tooltip]="{ enable: true, textStyle: { fontWeight: '900', size: '15px', color:'red', fontFamily: 'Roboto', fontStyle: 'Italic' } }">
</ejs-progressbar>
</div>
`
})
export class CustomTooltipComponent {
fileProgress = 50;
}Event Handling
Text Render Event
Customize the label/text displayed in the progress bar:
import { Component } from '@angular/core';
import { ProgressBarModule, ProgressAnnotationService } from '@syncfusion/ej2-angular-progressbar';
import { ITextRenderEventArgs, FontModel, AnimationModel } from '@syncfusion/ej2-progressbar';
@Component({
selector: 'app-text-render',
standalone: true,
imports: [ProgressBarModule],
providers: [ProgressAnnotationService],
template: `
<div style="margin: 20px;">
<!-- Custom text format -->
<div style="margin: 15px 0;">
<label>Custom Progress Text</label>
<ejs-progressbar
id="custom-text"
[value]="65"
type="Linear"
height="30"
[trackThickness]="24"
[progressThickness]="24"
[showProgressValue]="true"
[labelStyle]="labelStyle"
(textRender)="onTextRender($event)"
[animation]="animation"
style="width: 400px;">
</ejs-progressbar>
</div>
</div>
`
})
export class TextRenderComponent {
public animation?: AnimationModel;
public labelStyle?: FontModel;
ngOnInit() {
this.animation = { enable: true, duration: 2000, delay: 0 };
this.labelStyle = { color: '#FFFFFF', fontWeight: 'bold' };
}
onTextRender(args: ITextRenderEventArgs): void {
// Customize text display
args.text = args.value + '%'; // Default format
// Or use custom format
if (args.value && args.value >= 75) {
args.text = '✓ ' + args.value + '%';
} else if (args.value && args.value >= 50) {
args.text = '◐ ' + args.value + '%';
} else {
args.text = '◑ ' + args.value + '%';
}
}
}Advanced Text Rendering
@Component({
selector: 'app-advanced-text-render',
standalone: true,
imports: [ProgressBarModule],
providers: [ProgressAnnotationService],
template: `
<div style="margin: 20px;">
<!-- Download with MB display -->
<ejs-progressbar
id="download-text"
[value]="downloadPercent"
type="Linear"
height="25"
[trackThickness]="20"
[progressThickness]="20"
[showProgressValue]="true"
[labelStyle]="labelStyle"
(textRender)="formatDownloadText($event)"
style="width: 400px;">
</ejs-progressbar>
<p>Downloading: {{ downloadedMB }} MB / {{ totalMB }} MB</p>
</div>
`
})
export class AdvancedTextRenderComponent {
downloadPercent = 45;
downloadedMB = 450;
totalMB = 1000;
public labelStyle = { color: '#FFFFFF', fontWeight: 'bold', size: '14px' };
formatDownloadText(args: ITextRenderEventArgs): void {
args.text = `${this.downloadedMB}/${this.totalMB} MB`;
}
}Progress Value Changed Event
import { Component, ViewChild } from '@angular/core';
import { ProgressBarModule, ProgressBarComponent } from '@syncfusion/ej2-angular-progressbar'
import { IProgressValueEventArgs } from '@syncfusion/ej2-progressbar';
@Component({
selector: 'app-value-change',
standalone: true,
imports: [ProgressBarModule],
template: `
<div style="margin: 20px;">
<ejs-progressbar
#progress
[value]="currentValue"
type="Linear"
height="20"
(valueChanged)="onValueChange($event)">
</ejs-progressbar>
<button style="margin-top: 10px;" (click)="changeValue()">
Change Value
</button>
<p>Current Value: {{ currentValue }}%</p>
<p>Last Changed: {{ lastChanged }}</p>
</div>
`
})
export class ValueChangeComponent {
@ViewChild('progress', { static: false })
public progressBar?: ProgressBarComponent;
currentValue = 30;
lastChanged = 'Never';
public onValueChange(args: IProgressValueEventArgs): void {
this.lastChanged = new Date().toLocaleTimeString();
args.progressColor = '#2BB20E'; // optional visual change
}
public changeValue(): void {
if (this.progressBar) {
this.currentValue += 10;
if (this.currentValue > 100) {
this.currentValue = 20;
}
this.progressBar.value = this.currentValue;
}
}
}Progress Complete Event
@Component({
selector: 'app-complete-event',
standalone: true,
imports: [ProgressBarModule, CommonModule],
template: `
<div style="margin: 20px;">
<ejs-progressbar
[value]="progress"
type="Linear"
height="20"
(progressCompleted)="onComplete()">
</ejs-progressbar>
<button (click)="startProgress()" style="margin-top: 20px; padding: 8px 16px;">
Start Progress
</button>
<div *ngIf="completed" style="margin-top: 20px; padding: 15px;
background-color: #e8f5e9; color: #2e7d32;
border-radius: 4px;">
✓ Progress Complete!
</div>
</div>
`,
styles: [`
button {
background-color: #0078d4;
color: white;
border: none;
cursor: pointer;
border-radius: 4px;
}
`]
})
export class CompleteEventComponent {
progress = 0;
completed = false;
startProgress() {
this.progress = 0;
this.completed = false;
const interval = setInterval(() => {
this.progress += Math.random() * 25;
if (this.progress >= 100) {
this.progress = 100;
clearInterval(interval);
}
}, 200);
}
onComplete() {
this.completed = true;
}
}Multiple Event Handling
import { Component } from '@angular/core';
import { ProgressBarModule } from '@syncfusion/ej2-angular-progressbar'
import { IProgressValueEventArgs } from '@syncfusion/ej2-progressbar';
@Component({
selector: 'app-multi-events',
standalone: true,
imports: [ProgressBarModule],
template: `
<div style="margin: 20px;">
<ejs-progressbar
[value]="progress"
type="Linear"
height="20"
(valueChanged)="onValueChanged($event)"
(progressCompleted)="onComplete($event)">
</ejs-progressbar>
<div style="margin-top: 20px; padding: 15px; background-color: #f5f5f5;
border-radius: 4px; font-family: monospace; font-size: 12px;">
<p>{{ eventLog }}</p>
</div>
</div>
`,
styles: [`
p {
white-space: pre-wrap;
word-wrap: break-word;
margin: 0;
}
`]
})
export class MultiEventsComponent {
progress = 0;
eventLog = 'Waiting for events...\n';
onValueChanged(args: IProgressValueEventArgs) {
this.eventLog += `[${new Date().toLocaleTimeString()}] Value changed to ${args.value}%\n`;
}
onComplete(args: IProgressValueEventArgs) {
this.eventLog += `[${new Date().toLocaleTimeString()}] Completed!\n`;
}
ngOnInit() {
const interval = setInterval(() => {
this.progress += 5;
if (this.progress >= 100) {
this.progress = 100;
clearInterval(interval);
}
}, 300);
}
}Range Indicators
Color-Coded Ranges
@Component({
selector: 'app-range-indicators',
standalone: true,
imports: [ProgressBarModule],
template: `
<div style="margin: 20px;">
<h4>Progress Ranges</h4>
<!-- Low (0-33%) -->
<div style="margin: 15px 0;">
<label>Low Priority: {{ lowRange }}%</label>
<ejs-progressbar
id="lowProgress"
[value]="lowRange"
minimum="0"
maximum="100"
type="Linear"
height="20"
[progressColor]="'#FF9800'"
[trackColor]="'#FFE8D6'">
</ejs-progressbar>
</div>
<!-- Medium (33-66%) -->
<div style="margin: 15px 0;">
<label>Medium Priority: {{ mediumRange }}%</label>
<ejs-progressbar
id="mediumProgress"
[value]="mediumRange"
type="Linear"
minimum="0"
maximum="100"
height="20"
[progressColor]="'#FFC107'"
[trackColor]="'#FFF3E0'">
</ejs-progressbar>
</div>
<!-- High (66-100%) -->
<div style="margin: 15px 0;">
<label>High Priority: {{ highRange }}%</label>
<ejs-progressbar
id="highProgress"
[value]="highRange"
minimum="0"
maximum="100"
type="Linear"
height="20"
[progressColor]="'#4CAF50'"
[trackColor]="'#E8F5E9'">
</ejs-progressbar>
</div>
</div>
`
})
export class RangeIndicatorsComponent {
lowRange = 25;
mediumRange = 50;
highRange = 85;
}Critical Threshold Visualization
@Component({
selector: 'app-threshold-warning',
standalone: true,
imports: [ProgressBarModule, CommonModule],
template: `
<div style="margin: 20px;">
<h4>Storage Usage</h4>
<ejs-progressbar
[value]="storageUsage"
type="Linear"
height="25"
[progressColor]="getStorageColor()"
[trackColor]="'#e0e0e0'">
</ejs-progressbar>
<div style="margin-top: 10px; display: flex; justify-content: space-between;
font-size: 12px; color: #666;">
<span>0%</span>
<span>50%</span>
<span style="color: #F44336;">90% (Critical)</span>
<span>100%</span>
</div>
<p style="margin-top: 15px;">
Usage: {{ storageUsage }}GB / 100GB
<span *ngIf="storageUsage >= 90" style="color: #F44336;">
⚠️ Storage critical
</span>
</p>
</div>
`
})
export class ThresholdWarningComponent {
storageUsage = 85;
getStorageColor(): string {
if (this.storageUsage >= 90) return '#F44336'; // Red
if (this.storageUsage >= 70) return '#FF9800'; // Orange
return '#4CAF50'; // Green
}
}Reactive Data Binding
Two-Way Data Binding
import { Component, ViewChild } from '@angular/core';
import { ProgressBarModule } from '@syncfusion/ej2-angular-progressbar';
import { FormsModule } from '@angular/forms';
@Component({
selector: 'app-reactive-binding',
standalone: true,
imports: [ProgressBarModule, FormsModule],
template: `
<div style="margin: 20px;">
<h4>Real-time Progress Control</h4>
<div style="margin-bottom: 20px;">
<label>Progress Value:</label>
<input
type="number"
min="0"
max="100"
[(ngModel)]="progressValue"
style="padding: 5px; margin-left: 10px;">
</div>
<ejs-progressbar
[value]="progressValue"
type="Linear"
height="25">
</ejs-progressbar>
<p style="margin-top: 10px;">{{ progressValue }}%</p>
</div>
`
})
export class ReactiveBindingComponent {
progressValue = 50;
}Observable-Based Progress Updates
import { Observable, interval } from 'rxjs';
import { map, takeWhile } from 'rxjs/operators';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-observable-progress',
standalone: true,
imports: [ProgressBarModule, CommonModule],
template: `
<div style="margin: 20px;">
<h4>Observable-Based Progress</h4>
<ng-container *ngIf="currentProgress$ | async as progress">
<ejs-progressbar
[value]="progress"
type="Linear"
height="20">
</ejs-progressbar>
<p style="margin-top: 10px;">{{ (currentProgress$ | async) }}%</p>
</ng-container>
</div>
`
})
export class ObservableProgressComponent implements OnInit {
currentProgress$!: Observable<number>;
ngOnInit() {
this.currentProgress$ = interval(100).pipe(
map(x => (x * 5) % 101),
takeWhile(x => x <= 100 || x === 0)
);
}
}Form-Controlled Progress
import { FormControl, ReactiveFormsModule } from '@angular/forms';
@Component({
selector: 'app-form-progress',
standalone: true,
imports: [ProgressBarModule, ReactiveFormsModule],
template: `
<div style="margin: 20px;">
<h4>Form-Controlled Progress</h4>
<div style="margin-bottom: 20px;">
<label>Set Progress:</label>
<input
type="range"
min="0"
max="100"
[formControl]="progressControl"
style="margin-left: 10px; width: 300px;">
</div>
<ejs-progressbar
[value]="progressControl.value"
type="Linear"
[height]="25">
</ejs-progressbar>
<p>{{ progressControl.value }}%</p>
</div>
`,
styles: [`
input[type="range"] {
cursor: pointer;
}
`]
})
export class FormProgressComponent {
progressControl = new FormControl(50);
}Combined Example: Upload with All Features
@Component({
selector: 'app-full-featured',
standalone: true,
imports: [ProgressBarModule, CommonModule],
template: `
<div style="padding: 30px; max-width: 500px;">
<h3>Advanced File Upload</h3>
<ejs-progressbar
[value]="uploadProgress"
type="Linear"
height="30"
[animation]="{ enable: true, duration: 500 }"
(valueChanged)="onProgressChange($event)"
(progressCompleted)="onUploadComplete()">
</ejs-progressbar>
<div style="display: flex; justify-content: space-between; margin-top: 10px;">
<span>{{ uploadedSize }} MB / {{ totalSize }} MB</span>
<span [style.color]="getStatusColor()">{{ uploadStatus }}</span>
</div>
<button
(click)="startUpload()"
[disabled]="isUploading"
style="margin-top: 20px; padding: 10px 20px; cursor: pointer;
background-color: #0078d4; color: white; border: none;
border-radius: 4px;">
{{ isUploading ? 'Uploading...' : 'Start Upload' }}
</button>
<div *ngIf="uploadComplete" style="margin-top: 20px; padding: 15px;
background-color: #e8f5e9; color: #2e7d32;
border-radius: 4px;">
✓ Upload complete!
</div>
</div>
`
})
export class FullFeaturedComponent {
uploadProgress = 0;
uploadedSize = 0;
totalSize = 500;
uploadStatus = 'Ready';
isUploading = false;
uploadComplete = false;
startUpload() {
this.isUploading = true;
this.uploadComplete = false;
this.uploadProgress = 0;
this.uploadedSize = 0;
const interval = setInterval(() => {
this.uploadProgress += Math.random() * 20;
this.uploadedSize = Math.floor((this.uploadProgress / 100) * this.totalSize);
if (this.uploadProgress >= 100) {
this.uploadProgress = 100;
this.uploadedSize = this.totalSize;
clearInterval(interval);
this.isUploading = false;
}
}, 300);
}
onProgressChange(event: IProgressValueEventArgs) {
if (event.value < 30) {
this.uploadStatus = 'Initializing...';
} else if (event.value < 70) {
this.uploadStatus = 'Uploading...';
} else {
this.uploadStatus = 'Finalizing...';
}
}
onUploadComplete() {
this.uploadComplete = true;
this.uploadStatus = 'Complete!';
}
getStatusColor(): string {
if (this.uploadComplete) return '#4CAF50';
if (this.isUploading) return '#0078d4';
return '#666';
}
}Getting Started with Angular Progress Bar
Table of Contents
- Installation
- Step 1: Install the Progress Bar Package
- Step 2: Verify Installation
- Dependencies
- Module Setup
- Angular Standalone Components (Recommended)
- Traditional NgModule Setup (Angular <19)
- Basic Implementation
- Minimal Component
- Component with Type Property
- First Example
- Angular Standalone Architecture
- Import in Component
- Benefits
- Bootstrap Application
- Common Setup Issues
- Issue: Module Not Found Error
- Issue: Type Not Found in Template
Installation
Step 1: Install the Progress Bar Package
npm install @syncfusion/ej2-angular-progressbarThis will install the Progress Bar component and its dependencies.
Step 2: Verify Installation
Check your package.json to confirm the package is listed:
{
"dependencies": {
"@syncfusion/ej2-angular-progressbar": "^25.1.0",
"@angular/common": "^21.0.0",
"@angular/core": "^21.0.0"
}
}Dependencies
The Progress Bar component requires these minimum dependencies:
@syncfusion/ej2-angular-progressbar
├── @syncfusion/ej2-base
├── @syncfusion/ej2-data
└── @syncfusion/ej2-svg-baseThese are automatically installed with the main package.
Module Setup
Angular Standalone Components (Recommended)
For Angular 19+, use standalone components directly:
import { Component } from '@angular/core';
import { ProgressBarModule } from '@syncfusion/ej2-angular-progressbar';
@Component({
selector: 'app-progress-demo',
standalone: true,
imports: [ProgressBarModule],
template: `
<ejs-progressbar [value]="50"></ejs-progressbar>
`
})
export class ProgressDemoComponent {}Traditional NgModule Setup (Angular <19)
If using module-based architecture:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { ProgressBarModule } from '@syncfusion/ej2-angular-progressbar';
import { AppComponent } from './app.component';
@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule,
ProgressBarModule // Add here
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }Basic Implementation
Minimal Component
The simplest Progress Bar requires only:
import { Component } from '@angular/core';
import { ProgressBarModule } from '@syncfusion/ej2-angular-progressbar';
@Component({
selector: 'app-root',
standalone: true,
imports: [ProgressBarModule],
template: `
<ejs-progressbar
[value]="65">
</ejs-progressbar>
`
})
export class AppComponent {
}This renders a linear progress bar at 65% completion.
Component with Type Property
Specify the progress bar shape:
@Component({
selector: 'app-progress',
standalone: true,
imports: [ProgressBarModule],
template: `
<ejs-progressbar
[value]="75"
type="Linear">
</ejs-progressbar>
`
})
export class ProgressComponent {
}Valid types:
Linear- Horizontal or vertical bar (default)Circular- Circular shape
First Example
Complete working example with all essential parts:
import { Component } from '@angular/core';
import { ProgressBarModule } from '@syncfusion/ej2-angular-progressbar';
@Component({
selector: 'app-root',
standalone: true,
imports: [ProgressBarModule],
template: `
<div style="margin: 20px;">
<h3>File Download Progress</h3>
<!-- Linear Progress Bar -->
<div style="margin: 20px 0;">
<label>Download (Linear)</label>
<ejs-progressbar
id='linearProgress'
[value]="downloadProgress"
type="Linear">
</ejs-progressbar>
<p>{{ downloadProgress }}%</p>
</div>
<!-- Circular Progress Bar -->
<div style="margin: 20px 0;">
<label>Upload (Circular)</label>
<ejs-progressbar
[value]="uploadProgress"
type="Circular">
</ejs-progressbar>
<p>{{ uploadProgress }}%</p>
</div>
<button (click)="startProgress()">Start Progress</button>
</div>
`,
styles: [`
button {
padding: 8px 16px;
margin-top: 20px;
background-color: #0078d4;
color: white;
border: none;
cursor: pointer;
border-radius: 4px;
}
button:hover {
background-color: #005a9e;
}
`]
})
export class AppComponent {
downloadProgress = 30;
uploadProgress = 60;
startProgress() {
const interval = setInterval(() => {
this.downloadProgress += 5;
this.uploadProgress += 3;
if (this.downloadProgress >= 100) {
clearInterval(interval);
}
}, 200);
}
}HTML Output: Three progress bars demonstrating different shapes with a button to animate progress.
Angular Standalone Architecture
Starting with Angular 19, standalone components are the default. Key differences:
Import in Component
import { ProgressBarModule } from '@syncfusion/ej2-angular-progressbar';
@Component({
standalone: true,
imports: [ProgressBarModule] // Direct import
})
export class MyComponent {}Benefits
- No module declarations needed
- Smaller initial bundle
- Tree-shaking friendly
- Simpler mental model
Bootstrap Application
// main.ts
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app/app.component';
import 'zone.js';
bootstrapApplication(AppComponent)
.catch(err => console.error(err));Common Setup Issues
Issue: Module Not Found Error
Solution: Reinstall the package:
npm install @syncfusion/ej2-angular-progressbar --saveIssue: Type Not Found in Template
Solution: Ensure ProgressBarModule is imported in the component's imports array (standalone) or in NgModule (traditional).
Progress Modes in Angular Progress Bar
Table of Contents
- Determinate Mode
- Basic Determinate Progress
- User-Controlled Progress
- Minimum and Maximum Values
- Indeterminate Mode
- Basic Indeterminate Progress
- Indeterminate with Custom Height
- Circular Indeterminate
- Switching from Indeterminate to Determinate
- Buffer Mode
- Basic Buffer Progress
- Video Buffering Simulation
- Download with Speed Visualization
- Mode Selection Guidelines
- Real-World Scenarios
- Scenario 1: File Upload (Determinate)
- Scenario 2: Data Fetching (Indeterminate)
- Scenario 3: Multi-Step Process (Buffer)
- Combining Modes
- Transitioning Modes in One Component
Determinate Mode
Determinate mode shows explicit progress from 0 to 100%, used when you know the task duration or completion percentage.
Basic Determinate Progress
import { Component, ViewChild, OnInit } from '@angular/core';
import { ProgressBarModule } from '@syncfusion/ej2-angular-progressbar';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-determinate',
standalone: true,
imports: [ProgressBarModule],
template: `
<ejs-progressbar
[value]="progressValue"
type="Linear">
</ejs-progressbar>
<p>{{ progressValue }}% Complete</p>
`
})
export class DeterminateComponent {
progressValue = 45;
}User-Controlled Progress
@Component({
selector: 'app-user-progress',
standalone: true,
imports: [ProgressBarModule],
template: `
<div style="margin: 20px;">
<div>
<input
type="range"
min="0"
max="100"
[value]="progress"
(input)="onSliderChange($event)"
style="width: 100%;">
</div>
<ejs-progressbar
[value]="progress"
type="Linear"
height="25">
</ejs-progressbar>
<p>{{ progress }}% Complete</p>
</div>
`,
styles: [`
input[type="range"] {
margin-top: 10px;
}
`]
})
export class UserProgressComponent {
progress = 50;
onSliderChange(event: Event) {
const input = event.target as HTMLInputElement;
this.progress = parseInt(input.value);
}
}Minimum and Maximum Values
Customize the progress range:
@Component({
selector: 'app-custom-range',
standalone: true,
imports: [ProgressBarModule],
template: `
<!-- Progress from 10 to 90 with current value 50 -->
<ejs-progressbar
[minimum]="10"
[maximum]="90"
[value]="50"
type="Linear">
</ejs-progressbar>
`
})
export class CustomRangeComponent {
}Indeterminate Mode
Indeterminate mode shows animation without specific progress value, used when duration is unknown.
Basic Indeterminate Progress
@Component({
selector: 'app-indeterminate',
standalone: true,
imports: [ProgressBarModule],
template: `
<ejs-progressbar
[isIndeterminate]="true"
type="Linear" value=20>
</ejs-progressbar>
`
})
export class IndeterminateComponent {
}Indeterminate with Custom Height
<ejs-progressbar
[isIndeterminate]="true"
type="Linear"
height="8"
value=30>
</ejs-progressbar>Circular Indeterminate
<ejs-progressbar
[isIndeterminate]="true"
type="Circular"
value=30>
</ejs-progressbar>Switching from Indeterminate to Determinate
Transition from indeterminate to determinate when progress becomes known:
@Component({
selector: 'my-app',
standalone: true,
imports: [CommonModule, ProgressBarModule],
template: `
<div style="margin: 20px; width: 400px;">
<ejs-progressbar
#progressBar
[value]="progress"
[isIndeterminate]="isIndeterminate"
type="Linear"
height="20px"
width="100%">
</ejs-progressbar>
<p *ngIf="isIndeterminate">Loading...</p>
<p *ngIf="!isIndeterminate">
{{ progress | number:'1.0-0' }}% Complete
</p>
</div>
`
})
export class AppComponent {
@ViewChild('progressBar')
progressBar!: ProgressBarComponent;
progress = 0;
isIndeterminate = true;
ngOnInit() {
setTimeout(() => {
this.isIndeterminate = false;
setTimeout(() => {
this.progressBar.refresh();
this.startProgressUpdate();
});
}, 2000);
}
startProgressUpdate() {
const interval = setInterval(() => {
this.progress += Math.random() * 20;
if (this.progress >= 100) {
this.progress = 100;
clearInterval(interval);
}
}, 500);
}
}Buffer Mode
Buffer mode displays both primary progress and secondary progress (buffer). Used when content is being loaded ahead of playback.
Basic Buffer Progress
@Component({
selector: 'app-buffer-mode',
standalone: true,
imports: [ProgressBarModule],
template: `
<ejs-progressbar
[value]="primaryProgress"
[secondaryProgress]="bufferProgress"
type="Linear"
height="20">
</ejs-progressbar>
<p>Playing: {{ primaryProgress }}% | Buffered: {{ bufferProgress }}%</p>
`
})
export class BufferModeComponent {
primaryProgress = 35;
bufferProgress = 65;
}Video Buffering Simulation
@Component({
selector: 'app-video-buffering',
standalone: true,
imports: [ProgressBarModule, CommonModule],
template: `
<div style="margin: 20px;">
<h3>Video Playback</h3>
<ejs-progressbar
[value]="playbackProgress"
[secondaryProgress]="bufferProgress"
type="Linear"
height="8">
</ejs-progressbar>
<div style="font-size: 12px; margin-top: 5px;">
Playing: {{ formatTime(playbackProgress) }} |
Buffered: {{ formatTime(bufferProgress) }} |
Total: {{ formatTime(100) }}
</div>
<button (click)="play()" style="margin-top: 10px; padding: 8px 16px;">
{{ isPlaying ? 'Pause' : 'Play' }}
</button>
</div>
`,
styles: [`
button {
background-color: #0078d4;
color: white;
border: none;
cursor: pointer;
border-radius: 4px;
}
`]
})
export class VideoBufferingComponent {
playbackProgress = 0;
bufferProgress = 0;
isPlaying = false;
playbackInterval: any;
bufferInterval: any;
play() {
this.isPlaying = !this.isPlaying;
if (this.isPlaying) {
// Playback moves slower
this.playbackInterval = setInterval(() => {
this.playbackProgress += 0.5;
if (this.playbackProgress >= 100) {
clearInterval(this.playbackInterval);
this.isPlaying = false;
}
}, 100);
// Buffer advances faster
this.bufferInterval = setInterval(() => {
if (this.bufferProgress < 100) {
this.bufferProgress += Math.random() * 2;
}
}, 200);
} else {
clearInterval(this.playbackInterval);
clearInterval(this.bufferInterval);
}
}
formatTime(percent: number): string {
const seconds = Math.floor((percent / 100) * 300);
const mins = Math.floor(seconds / 60);
const secs = seconds % 60;
return `${mins}:${secs.toString().padStart(2, '0')}`;
}
ngOnDestroy() {
clearInterval(this.playbackInterval);
clearInterval(this.bufferInterval);
}
}Download with Speed Visualization
@Component({
selector: 'app-download-buffer',
standalone: true,
imports: [ProgressBarModule],
template: `
<div style="margin: 20px;">
<h3>File Download</h3>
<ejs-progressbar
[value]="downloadProgress"
[secondaryProgress]="verifyProgress"
type="Linear"
height="20">
</ejs-progressbar>
<div style="margin-top: 10px; font-size: 14px;">
<div>Downloaded: {{ downloadProgress }}%</div>
<div>Verified: {{ verifyProgress }}%</div>
</div>
</div>
`
})
export class DownloadBufferComponent implements OnInit {
downloadProgress = 0;
verifyProgress = 0;
ngOnInit() {
// Download phase
const downloadInterval = setInterval(() => {
this.downloadProgress += Math.random() * 15;
if (this.downloadProgress >= 100) {
this.downloadProgress = 100;
clearInterval(downloadInterval);
}
}, 300);
// Verification phase (lags behind)
const verifyInterval = setInterval(() => {
if (this.verifyProgress < this.downloadProgress - 10) {
this.verifyProgress += Math.random() * 10;
}
}, 400);
}
}Mode Selection Guidelines
| Mode | When to Use | Example | Known % |
|---|---|---|---|
| Determinate | Progress is measurable | File upload (50/100 MB) | ✓ Yes |
| Indeterminate | Duration unknown | API request loading | ✗ No |
| Buffer | Multi-stage progress | Video playback (play vs buffer) | ✓ Primary + Secondary |
Real-World Scenarios
Scenario 1: File Upload (Determinate)
@Component({
selector: 'app-file-upload',
standalone: true,
imports: [ProgressBarModule],
template: `
<ejs-progressbar
[value]="uploadProgress"
type="Linear"
height="20">
</ejs-progressbar>
<p>{{ uploadedSize }} MB / {{ totalSize }} MB</p>
`
})
export class FileUploadComponent {
uploadedSize = 50;
totalSize = 100;
get uploadProgress(): number {
return (this.uploadedSize / this.totalSize) * 100;
}
}Scenario 2: Data Fetching (Indeterminate)
@Component({
selector: 'app-root',
standalone: true,
imports: [CommonModule, ProgressBarModule],
template: `
<ejs-progressbar
*ngIf="isLoading"
[isIndeterminate]="true"
value=30
type="Linear"
height="4"
width="100%">
</ejs-progressbar>
<p *ngIf="isLoading">Loading...</p>
<p *ngIf="!isLoading">✅ Data Loaded</p>
`
})
export class AppComponent {
isLoading = true;
// Simulate API loading
ngOnInit() {
setTimeout(() => {
this.isLoading = false;
}, 2000);
}
}Scenario 3: Multi-Step Process (Buffer)
@Component({
selector: 'app-root',
standalone: true,
imports: [CommonModule, ProgressBarModule],
template: `
<div style="max-width: 500px;">
<h4>Processing: Download → Process → Upload</h4>
<!-- Buffer progress bar -->
<ejs-progressbar
[value]="currentProgress"
[secondaryProgress]="bufferProgress"
type="Linear"
height="20"
width="100%">
</ejs-progressbar>
<p>
Current: {{ currentStepName }} |
Progress: {{ currentProgress | number:'1.0-0' }}%
</p>
</div>
`
})
export class AppComponent implements OnInit {
currentProgress = 0; // primary progress
bufferProgress = 0; // secondary (buffer) progress
currentStepName = 'Downloading';
ngOnInit() {
const interval = setInterval(() => {
// ---- Step 1: Download (0–33%) ----
if (this.currentProgress < 33) {
this.currentStepName = 'Downloading';
this.currentProgress += 2;
this.bufferProgress = Math.min(this.currentProgress + 10, 33);
}
// ---- Step 2: Process (33–66%) ----
else if (this.currentProgress < 66) {
this.currentStepName = 'Processing';
this.currentProgress += 2;
this.bufferProgress = Math.min(this.currentProgress + 10, 66);
}
// ---- Step 3: Upload (66–100%) ----
else if (this.currentProgress < 100) {
this.currentStepName = 'Uploading';
this.currentProgress += 2;
this.bufferProgress = Math.min(this.currentProgress + 10, 100);
}
// ---- Done ----
else {
this.currentStepName = 'Completed ✅';
this.currentProgress = 100;
this.bufferProgress = 100;
clearInterval(interval);
}
}, 300);
}
}
``Combining Modes
Transitioning Modes in One Component
@Component({
selector: 'my-app',
standalone: true,
imports: [CommonModule, ProgressBarModule],
template: `
<ejs-progressbar
*ngIf="mode !== 'indeterminate'"
type="Linear"
height="20"
[value]="progress"
[secondaryProgress]="mode === 'buffer' ? secondaryValue : null">
</ejs-progressbar>
<ejs-progressbar
*ngIf="mode === 'indeterminate'"
type="Linear"
height="20"
[value]="progress"
[isIndeterminate]="true">
</ejs-progressbar>
<p>Mode: {{ mode }} | Progress: {{ progress }}%</p>
<div>
<button (click)="setMode('determinate')">Determinate</button>
<button (click)="setMode('indeterminate')">Indeterminate</button>
<button (click)="setMode('buffer')">Buffer</button>
</div>
`
})
export class AppComponent {
mode: 'determinate' | 'indeterminate' | 'buffer' = 'determinate';
progress = 0;
secondaryValue = 0;
private intervalId: any;
setMode(newMode: typeof this.mode) {
this.clearInterval();
this.mode = newMode;
if (newMode === 'indeterminate') {
this.progress = 20; // logical value only
return;
}
this.progress = 0;
this.secondaryValue = 0;
this.intervalId = setInterval(() => {
this.progress += 10;
if (this.mode === 'buffer') {
this.secondaryValue = Math.min(100, this.progress + 20);
}
if (this.progress >= 100) {
this.clearInterval();
}
}, 300);
}
private clearInterval() {
if (this.intervalId) {
clearInterval(this.intervalId);
this.intervalId = null;
}
}
}Types and Shapes in Angular Progress Bar
Table of Contents
- Linear Progress Bar
- Basic Linear Progress
- Linear with Secondary Progress Buffer
- Circular Progress Bar
- Basic Circular Progress
- Circular with Custom Radius
- Compact Circular Progress
- Semi-Circular Progress Bar
- Basic Semi-Circular Progress
- Customized Semi-Circular
- Type-Specific Properties
- Linear-Specific Properties
- Circular-Specific Properties
- Switching Between Types
- When to Use Each Type
- Linear Progress Bar Type
- Circular Progress Bar Type
- Semi-Circular Progress Bar Type
- Complete Type Comparison Example
- Changing Properties by Type
- Performance Tips
Linear Progress Bar
Linear progress bars display progress horizontally (default) or vertically. They're ideal for simple progress tracking.
Basic Linear Progress
import { Component } from '@angular/core';
import { ProgressBarModule } from '@syncfusion/ej2-angular-progressbar';
@Component({
selector: 'app-linear-progress',
standalone: true,
imports: [ProgressBarModule],
template: `
<ejs-progressbar
[value]="75"
type="Linear"
height="20">
</ejs-progressbar>
`
})
export class LinearProgressComponent {
}Linear with Secondary Progress (Buffer)
Display two progress states simultaneously:
@Component({
selector: 'app-buffer-progress',
standalone: true,
imports: [ProgressBarModule],
template: `
<ejs-progressbar
[value]="40"
[secondaryProgress]="70"
type="Linear"
height="20">
</ejs-progressbar>
`,
styles: [`
:host ::ng-deep .e-progress {
background-color: #f0f0f0;
}
:host ::ng-deep .e-secondary-progress {
background-color: #d0d0d0;
}
`]
})
export class BufferProgressComponent {
}Use Case: Video buffering (primary: playing, secondary: buffered)
Circular Progress Bar
Circular progress bars provide a more visual, space-efficient representation of progress.
Basic Circular Progress
@Component({
selector: 'app-circular-progress',
standalone: true,
imports: [ProgressBarModule],
template: `
<ejs-progressbar
[value]="60"
type="Circular">
</ejs-progressbar>
`
})
export class CircularProgressComponent {
}Circular with Custom Radius
Adjust the inner and outer radius:
@Component({
selector: 'app-custom-circular',
standalone: true,
imports: [ProgressBarModule],
template: `
<ejs-progressbar
[value]="75"
type="Circular"
radius="150"
height="400"
innerRadius="100">
</ejs-progressbar>
`
})
export class CustomCircularComponent {
}Properties:
radius- Outer radius of the circle (default: 100)innerRadius- Inner radius for donut-style appearance
Compact Circular Progress
<ejs-progressbar
[value]="85"
type="Circular"
height="200"
radius="80"
innerRadius="60">
</ejs-progressbar>Semi-Circular Progress Bar
Semi-circular progress bars display progress as a half-circle, ideal for dashboard widgets and status displays.
Basic Semi-Circular Progress
@Component({
selector: 'app-semi-circular-progress',
standalone: true,
imports: [ProgressBarModule],
template: `
<ejs-progressbar
[value]="70"
type="SemiCircular"
height="300"
width="300">
</ejs-progressbar>
`
})
export class SemiCircularProgressComponent {
}Customized Semi-Circular
@Component({
selector: 'app-custom-semi-circular',
standalone: true,
imports: [ProgressBarModule],
template: `
<ejs-progressbar
[value]="65"
type="SemiCircular"
height="300"
width="300"
radius="150"
innerRadius="100"
cornerRadius="Round"
trackColor="#e0e0e0"
progressColor="#2196F3"
[trackThickness]="40"
[progressThickness]="40">
</ejs-progressbar>
`
})
export class CustomSemiCircularComponent {
}Use Case: Dashboard metrics, battery level indicators, completion status in admin panels
Type-Specific Properties
Linear-Specific Properties
| Property | Type | Description |
|---|---|---|
width | number\ | string |
height | number | Height of the progress bar SVG Container |
trackThickness | number | Track line thickness |
progressThickness | number | Progress bar thickness |
secondaryProgressThickness | number | Secondary progress thickness |
Circular-Specific Properties
| Property | Type | Description |
|---|---|---|
radius | number\ | string |
innerRadius | number\ | string |
cornerRadius | string | 'Round' \ |
Switching Between Types
Dynamically change progress bar type based on user preference or layout:
@Component({
selector: 'app-switch-types',
standalone: true,
imports: [ProgressBarModule, CommonModule],
template: `
<div style="margin: 20px;">
<label>Progress Bar Type:</label>
<select (change)="onTypeChange($event)">
<option value="Linear">Linear</option>
<option value="Circular">Circular</option>
</select>
<div style="margin-top: 20px;">
<ejs-progressbar
*ngIf="selectedType === 'Linear'"
id="linearBar"
type="Linear"
[value]="50"
height="20"
style="width:300px;">
</ejs-progressbar>
<ejs-progressbar
*ngIf="selectedType === 'Circular'"
id="circularBar"
type="Circular"
[value]="50"
width="120"
height="120">
</ejs-progressbar>
</div>
</div>
`,
styles: [`
select {
padding: 8px;
font-size: 14px;
}
`]
})
export class SwitchTypesComponent {
selectedType = 'Linear';
onTypeChange(event: Event) {
const target = event.target as HTMLSelectElement;
this.selectedType = target.value;
}
}When to Use Each Type
Linear Progress Bar Type
When to use:
- File uploads/downloads
- Loading bars at the top of pages
- Process steps (vertical orientation)
- Simple progress indicators
- Space-constrained layouts (horizontal)
Example:
<ejs-progressbar
[value]="progress"
type="Linear"
height="4">
</ejs-progressbar>Circular Progress Bar Type
When to use:
- Dashboard metrics and KPIs
- Quota or capacity indicators
- Skill proficiency displays
- System resource usage
- Central focal point designs
Example:
<ejs-progressbar
[value]="completionRate"
type="Circular">
</ejs-progressbar>Semi-Circular Progress Bar Type
When to use:
- Status displays in widgets
- Battery or fuel level indicators
- Speedometer-like visualizations
- Gauge-style progress indicators
- Space-limited dashboard panels
Example:
<ejs-progressbar
[value]="statusLevel"
type="SemiCircular"
height="300"
width="300">
</ejs-progressbar>Complete Type Comparison Example
Display all three types side-by-side:
@Component({
selector: 'app-type-comparison',
standalone: true,
imports: [ProgressBarModule],
template: `
<div style="display: flex; gap: 40px; padding: 20px; flex-wrap: wrap;">
<!-- Linear -->
<div>
<h4>Linear (75%)</h4>
<ejs-progressbar
id="linear"
[value]="75"
type="Linear"
height="20"
style="width: 200px;">
</ejs-progressbar>
</div>
<!-- Circular -->
<div>
<h4>Circular (75%)</h4>
<ejs-progressbar
id="circular"
[value]="75"
type="Circular"
height="200"
width="200">
</ejs-progressbar>
</div>
<!-- Semi-Circular -->
<div>
<h4>Semi-Circular (75%)</h4>
<ejs-progressbar
id="semicircular"
[value]="75"
type="SemiCircular"
height="200"
width="200">
</ejs-progressbar>
</div>
</div>
`
})
export class TypeComparisonComponent {
}Changing Properties by Type
Different types support different properties:
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-adaptive-properties',
standalone: true,
imports: [ProgressBarModule, CommonModule],
template: `
<!-- Linear Progress Bar -->
<ejs-progressbar
*ngIf="isLinear"
id="linearBar"
type="Linear"
[value]="60"
height="20"
style="width:300px;">
</ejs-progressbar>
<!-- Circular Progress Bar -->
<ejs-progressbar
*ngIf="isCircular"
id="circularBar"
height="300"
type="Circular"
[value]="60"
radius="120"
innerRadius="50">
</ejs-progressbar>
`
})
export class AdaptivePropertiesComponent {
type: 'Linear' | 'Circular' = 'Linear';
get isLinear() {
return this.type === 'Linear';
}
get isCircular() {
return this.type === 'Circular' || this.type === 'SemiCircular';
}
}Performance Tips
- Linear: Minimal CPU usage, best for frequent updates
- Circular: Moderate CPU usage, smooth scaling
For high-frequency updates (every 10ms), use Linear type for best performance.