A nice Gem inside Angular
What Are viewProviders in Angular?
In Angular, providers define how to supply a dependency to a component and its children. When you register a service in the providers array of a component, Angular makes that service available to:
- The component itself
- Its template
- Any child components
- And even content projected using
<ng-content>
However, Angular also gives you a more restrictive option: viewProviders.
What Is viewProviders?
The viewProviders array works like providers, but with one key difference: it limits the visibility of the service to the component’s view only.
This means:
- The service is accessible to the component and elements declared in its own template
- It is not accessible to content projected from outside (via
<ng-content>) - It is also not available to external child components rendered via projection
In short: viewProviders allow you to encapsulate a service strictly within the component’s own view, preventing it from being accessed by nested or projected components.
providers vs viewProviders Scope
Here’s the difference:
providers: Service is visible everywhere within the component, including projected content.viewProviders: Service is visible only to the component’s view—not to projected content.
This may seem like a subtle difference, but it’s crucial for creating reusable, predictable components that don’t accidentally expose internal services to outside templates.
Use Case: Modal with Projected Content
Let’s see this in action with a ModalComponent.
Get Manolis Xhani Trungu’s stories in your inbox
Join Medium for free to get updates from this writer.
Say you’re building a modal component that controls its own visibility (open/close), and you want to encapsulate that logic in a ModalStateService.
But — here’s the twist — you allow arbitrary content to be projected inside the modal (via <ng-content>), and you don’t want that projected content to mess with the modal’s internal state.
ModalComponent using viewProviders
@Component({
selector: 'app-modal',
template: `
<section class="modal" *ngIf="!state.isClosed()">
<header class="modal-header">
<h2>{{ title() }}</h2>
<button (click)="close()">X</button>
</header>
<div class="modal-body">
<ng-content></ng-content>
</div>
</section>
`,
styleUrls: ['./modal.component.scss'],
viewProviders: [ModalStateService],
})
export class ModalComponent {
private readonly state = inject(ModalStateService);
title = input.required<string>();
close() {
this.state.close();
}
}ModalStateService
@Injectable()
export class ModalStateService {
private readonly _closed = signal(false);
readonly isClosed = this._closed.asReadonly();
close(): void {
this._closed.set(true);
}
open(): void {
this._closed.set(false);
}
}Projected Content Attempting to Use the Service
@Component({
selector: 'app-modal-body',
template: `
<p>This is custom content injected into the modal.</p>
<button (click)="attemptClose()">Try Close Modal</button>
`,
})
export class ModalBodyComponent {
// ❌ This will throw an error if `ModalStateService` is in `viewProviders`
private readonly state = inject(ModalStateService);
attemptClose() {
this.state.close();
}
}Usage
<app-modal title="Example Modal">
<app-modal-body></app-modal-body>
</app-modal>Why It Matters
In the example above:
- The
ModalStateServiceis scoped only to the view ofModalComponent - The projected
ModalBodyComponentcannot inject or modify the modal’s internal state
Had we used the broader providers array, ModalBodyComponent would have been able to inject the state service—possibly altering the modal’s behavior unexpectedly.
This kind of tight coupling is dangerous, especially in component libraries or reusable UI systems. By using viewProviders, we maintain encapsulation, reduce side effects, and build predictable components.
Summary
- Use
providersif you want a service to be accessible by the component, its children, and any projected content. - Use
viewProvidersto restrict the service to the component’s own view. - This technique is essential when building components that are meant to be modular, isolated, and secure from external interference.
Think of
viewProvidersas your component’s private state locker—it’s safe, secure, and invisible to outsiders.










