ProgressRing Component synced with Web Awesome 3.0.0
Preparing for Web Awesome 1.0.0. This wrapper will not target a version above 1.0.0 until it is released.
Overview
Import
Import the progressRing directive from the angular-awesome package:
// Import the progressRing directive
import { WaProgressRingDirective } from 'angular-awesome/progress-ring';
Examples
Progress Ring Examples
Progress rings are used to show the progress of a determinate operation in a circular fashion.
Basic
<wa-progress-ring value="25"></wa-progress-ring>
Size
Use the --size custom property to set the diameter of the progress ring.
<wa-progress-ring value="50" style="--size: 200px;"></wa-progress-ring>
Track and Indicator Width
Use the --track-width and --indicator-width custom properties to set the width of the progress ring's track and indicator.
<wa-progress-ring value="50" style="--track-width: 6px; --indicator-width: 12px;"></wa-progress-ring>
Colors
To change the color, use the --track-color and --indicator-color custom properties.
<wa-progress-ring
value="50"
style="
--track-color: pink;
--indicator-color: deeppink;
"
>
</wa-progress-ring>
Labels
Use the default slot to show a label inside the progress ring.
<wa-progress-ring value="50" class="progress-ring-values" style="margin-bottom: .5rem;">50%</wa-progress-ring>
<br />
<wa-button circle><wa-icon name="minus" variant="solid" label="Decrease"></wa-icon></wa-button>
<wa-button circle><wa-icon name="plus" variant="solid" label="Increase"></wa-icon></wa-button>
<script>
const progressRing = document.querySelector('.progress-ring-values');
const subtractButton = progressRing.nextElementSibling.nextElementSibling;
const addButton = subtractButton.nextElementSibling;
addButton.addEventListener('click', () => {
const value = Math.min(100, (progressRing.value || 50) + 10);
progressRing.value = value;
progressRing.textContent = `${value}%`;
});
subtractButton.addEventListener('click', () => {
const value = Math.max(0, (progressRing.value || 50) - 10);
progressRing.value = value;
progressRing.textContent = `${value}%`;
});
</script>
Angular bindings (alternative)
The same can be expressed using Angular inputs (mapped to CSS variables) and ngModel.
<!-- Different sizes via [size] input (maps to --size) -->
<wa-progress-ring value="60" [size]="'100px'"></wa-progress-ring>
<wa-progress-ring value="60" [size]="'150px'"></wa-progress-ring>
<wa-progress-ring value="60" [size]="'200px'"></wa-progress-ring>
<!-- Custom styling via inputs that map to CSS variables -->
<wa-progress-ring value="40" [trackWidth]="'4px'" [trackColor]="'#e0e0e0'"></wa-progress-ring>
<wa-progress-ring value="65" [indicatorWidth]="'6px'" [indicatorColor]="'#4caf50'"></wa-progress-ring>
<wa-progress-ring value="80" [indicatorTransitionDuration]="'1.5s'"></wa-progress-ring>
<wa-progress-ring value="70" [size]="'120px'" [trackWidth]="'3px'" [trackColor]="'#f5f5f5'" [indicatorWidth]="'5px'" [indicatorColor]="'#2196f3'" [indicatorTransitionDuration]="'0.8s'"></wa-progress-ring>
Using with Angular Bindings
import { Component } from '@angular/core';
@Component({
selector: 'app-progress-demo',
template: `
<wa-progress-ring
[value]="progressValue"
[label]="progressLabel"
[size]="ringSize"
[trackWidth]="trackWidth"
[trackColor]="trackColor"
[indicatorWidth]="indicatorWidth"
[indicatorColor]="indicatorColor"
[indicatorTransitionDuration]="transitionDuration"
(focusEvent)="onFocus()"
(blurEvent)="onBlur()">
</wa-progress-ring>
<div class="controls">
<button (click)="incrementProgress()">Increment</button>
<button (click)="resetProgress()">Reset</button>
</div>
`
})
export class ProgressRingDemoComponent {
progressValue = 25;
progressLabel = 'Loading...';
ringSize = '120px';
trackWidth = '4px';
trackColor = '#e0e0e0';
indicatorWidth = '4px';
indicatorColor = '#2196f3';
transitionDuration = '0.3s';
incrementProgress(): void {
if (this.progressValue < 100) {
this.progressValue += 10;
this.updateLabel();
}
}
resetProgress(): void {
this.progressValue = 0;
this.updateLabel();
}
updateLabel(): void {
this.progressLabel = `Loading ${this.progressValue}%`;
}
onFocus(): void {
console.log('Progress ring focused');
}
onBlur(): void {
console.log('Progress ring blurred');
}
}
Using with ngModel
<form #progressForm="ngForm">
<wa-progress-ring
[(ngModel)]="downloadProgress"
name="downloadProgress">
</wa-progress-ring>
<div>Current progress: {{ downloadProgress }}%</div>
<input
type="range"
min="0"
max="100"
[(ngModel)]="downloadProgress"
name="progressSlider">
</form>
Real-World Example: File Upload with Progress Ring
import { Component } from '@angular/core';
import { HttpClient, HttpEventType } from '@angular/common/http';
@Component({
selector: 'app-file-upload',
template: `
<div class="upload-container">
<h2>File Upload</h2>
<div class="upload-area">
<input
type="file"
(change)="onFileSelected($event)"
[disabled]="uploading">
<div class="progress-container" *ngIf="uploading">
<wa-progress-ring
[value]="uploadProgress"
[label]="uploadProgressLabel"
[size]="'150px'"
[indicatorColor]="'#4caf50'"
[indicatorTransitionDuration]="'0.3s'">
</wa-progress-ring>
</div>
</div>
<div class="status" *ngIf="uploadComplete">
Upload complete!
</div>
<div class="error" *ngIf="uploadError">
{{ errorMessage }}
</div>
</div>
`,
styles: [`
.upload-container {
display: flex;
flex-direction: column;
align-items: center;
gap: 20px;
}
.upload-area {
position: relative;
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
}
.progress-container {
margin-top: 20px;
}
`]
})
export class FileUploadComponent {
uploading = false;
uploadProgress = 0;
uploadProgressLabel = '';
uploadComplete = false;
uploadError = false;
errorMessage = '';
constructor(private http: HttpClient) {}
onFileSelected(event: Event): void {
const fileInput = event.target as HTMLInputElement;
if (fileInput.files && fileInput.files.length > 0) {
const file = fileInput.files[0];
this.uploadFile(file);
}
}
uploadFile(file: File): void {
this.uploading = true;
this.uploadComplete = false;
this.uploadError = false;
this.uploadProgress = 0;
this.updateProgressLabel();
const formData = new FormData();
formData.append('file', file);
this.http.post('https://api.example.com/upload', formData, {
reportProgress: true,
observe: 'events'
}).subscribe({
next: (event) => {
if (event.type === HttpEventType.UploadProgress) {
if (event.total) {
this.uploadProgress = Math.round(100 * event.loaded / event.total);
this.updateProgressLabel();
}
} else if (event.type === HttpEventType.Response) {
this.uploading = false;
this.uploadComplete = true;
}
},
error: (error) => {
this.uploading = false;
this.uploadError = true;
this.errorMessage = 'Upload failed: ' + error.message;
}
});
}
updateProgressLabel(): void {
this.uploadProgressLabel = `${this.uploadProgress}%`;
}
}
Multiple Progress Rings for Dashboard
<div class="dashboard">
<div class="metric">
<h3>CPU Usage</h3>
<wa-progress-ring
value="85"
[size]="'100px'"
[indicatorColor]="'#f44336'"
label="85%">
</wa-progress-ring>
</div>
<div class="metric">
<h3>Memory</h3>
<wa-progress-ring
value="60"
[size]="'100px'"
[indicatorColor]="'#2196f3'"
label="60%">
</wa-progress-ring>
</div>
<div class="metric">
<h3>Disk Space</h3>
<wa-progress-ring
value="45"
[size]="'100px'"
[indicatorColor]="'#4caf50'"
label="45%">
</wa-progress-ring>
</div>
<div class="metric">
<h3>Network</h3>
<wa-progress-ring
value="30"
[size]="'100px'"
[indicatorColor]="'#ff9800'"
label="30%">
</wa-progress-ring>
</div>
</div>
Progress Ring with Custom Content
<wa-progress-ring value="65" [size]="'150px'">
<div style="display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100%;">
<strong style="font-size: 24px;">65%</strong>
<span>Complete</span>
</div>
</wa-progress-ring>
Animated Progress Ring
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-animated-progress',
template: `
<wa-progress-ring
[value]="currentValue"
[size]="'150px'"
[indicatorColor]="'#673ab7'"
[indicatorTransitionDuration]="'0.5s'">
<div class="content">
<strong>{{ currentValue }}%</strong>
</div>
</wa-progress-ring>
`,
styles: [`
.content {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
font-size: 24px;
}
`]
})
export class AnimatedProgressComponent implements OnInit {
currentValue = 0;
ngOnInit(): void {
this.animateProgress();
}
animateProgress(): void {
const interval = setInterval(() => {
if (this.currentValue < 100) {
this.currentValue += 1;
} else {
clearInterval(interval);
}
}, 50);
}
}