Service

WrLoadingBar

Top-of-page progress bar with a start() / complete() slot API for HTTP interceptors or any long-running task. Add provideWrLoadingBarRouter() and router navigations drive it as well — an opt-in, because that subscription is what would otherwise pull @angular/router into an app that never routes.

Install

import { WrLoadingBar, WrLoadingBarComponent } from 'ngwr/loading-bar';

@Component({
  selector: 'app-shell',
  template: `
    <wr-loading-bar />
    <router-outlet />
  `,
  imports: [WrLoadingBarComponent, RouterOutlet],
})
export class AppShell {
  // Inject once at the shell so the singleton exists before the first
  // navigation. The subscription itself comes from provideWrLoadingBarRouter().
  constructor() {
    inject(WrLoadingBar);
  }
}

Live demo

Click below — the bar at the top of this page ticks. This site adds provideWrLoadingBarRouter(), so changing page drives it too.

progress: 0 · state: idle

HTTP interceptor

Slot-counted — multiple concurrent requests stack, bar stays running until the last finishes.

// HttpInterceptor — start a slot per pending HTTP request.
import { HttpInterceptorFn } from '@angular/common/http';
import { inject } from '@angular/core';
import { finalize } from 'rxjs';
import { WrLoadingBar } from 'ngwr/loading-bar';

export const loadingInterceptor: HttpInterceptorFn = (req, next) => {
  const bar = inject(WrLoadingBar);
  bar.start();
  return next(req).pipe(finalize(() => bar.complete()));
};

Styling

<!-- Customise color + thickness via attributes. -->
<wr-loading-bar color="var(--wr-color-warning)" height="3px" />

Why ngwr provides this

A router-aware progress bar needs router event wiring, debounce against quick navigations, and manual start/stop for HTTP work. The service centralizes that instead of leaving it to every app shell.

API

NameDescriptionTypeDefault
WrLoadingBarInjectable service — the singleton every bar reads.service
start()Open a slot. While at least one slot is open, the bar trickles asymptotically toward 90%.() => void
complete()Close one slot. When the last closes, the bar fast-forwards to 100% then resets.() => void
reset()Abort — clear every slot and hide the bar immediately, without animating to 100%.() => void
progressLive progress signal [0, 1]. Useful for custom UIs.Signal<number>0
stateComputed lifecycle: idle / running / completing.Signal<WrLoadingState>'idle'
<wr-loading-bar>Visual element. Reads the singleton service.component
colorBar colour — any CSS colour value.string'var(--wr-color-primary)'
heightBar height.string'2px'