While working with PrimeNG and PrimeFlex in my Angular 17 standalone app that uses SSR, one feature really impressed me: the out-of-the-box themes. In contrast to Material UI, PrimeNG supplies a rich set of ready-made themes that you can seamlessly integrate into your project.
The true highlight, however, was adding a theme switcher that lets users customize their interface. Achieving this requires surprisingly minimal code. In this walkthrough, I'll show you exactly how.
Preparing Your Application for Theme Configuration:
First, install the required package via npm or yarn.
npm install primeng --save
Add Styles to angular.json:
Your angular.json file must reference the necessary style files. Shown below is my directory layout along with how I referenced it in angular.json.
Every stylesheet pulled in one of the preinstalled PrimeNG themes supplied via the resources directory.
//angular.json
"styles": [
"src/styles.css",
{
"input": "src/app/styles/lara-dark-teal.scss",
"bundleName": "lara-dark-teal",
"inject": false
},
{
"input": "src/app/styles/lara-light-teal.scss",
"bundleName": "lara-light-teal",
"inject": false
}
],
With this setup, the CSS files are ensured to be included in your production dist directory when the build runs.
- Configuring the Initial Theme (index.html):
Add the Stylesheet: Inside your index.html, insert the link to your selected default theme's stylesheet and give it an identifier so the service can reference it later:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Theme Switcher</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<link id="app-theme" rel="stylesheet" type="text/css" href="lara-light-teal.css">
<link rel="stylesheet" href="https://unpkg.com/primeflex@latest/primeflex.css">
</head>
<body class="">
<app-root></app-root>
</body>
</html>
- Dynamic Theme Switching with a Service:
Build a service that handles theme toggling. Provide it at the root component level so it can be injected anywhere in the app:
//themes.service.ts
import { Inject, Injectable } from '@angular/core';
import { DOCUMENT } from '@angular/common';
@Injectable({
providedIn: 'root',
})
export class ThemeService {
constructor(@Inject(DOCUMENT) private document: Document) {}
switchTheme(theme: string) {
let themeLink = this.document.getElementById('app-theme') as HTMLLinkElement;
if (themeLink) {
themeLink.href = theme + '.css';
}
}
}
- Consuming the service within a component:
Bring the ThemeService and Document into your component by injecting them:
constructor(private themeService: ThemeService) {
}
checked: boolean = false;
changeTheme() {
let theme = (this.checked) ? "lara-dark-teal" : "lara-light-teal"
this.themeService.switchTheme(theme);
}
}
Render the toggle control using PrimeNG’s p-toggle component. Connect its checked state to a boolean property, and call the changeTheme() handler upon user interaction. For a polished look, make use of pi-icons from PrimeNG’s icon set.
<p-toolbar styleClass="bg-primary shadow-2 opacity-80">
<div class="flex-grow">
My Theme Switcher
</div>
<p-toggleButton styleClass="bg-primary shadow-2 text-white" [(ngModel)]="checked" onIcon="pi pi-sun"
offIcon="pi pi-moon" (click)="changeTheme()" />
</p-toolbar>
Separation of Concerns: Theme logic lives entirely within the service, so your component stays lean and purposeful.
Enhanced Readability: The implementation is cleanly organized, making it straightforward for any developer to follow.
Developer Delight: PrimeNG simplifies the heavy lifting, letting you build a smooth theme-switching experience in your Angular 17 app with ease.

