Logo

How to dynamically change header based on AngularJS partial view?

When building single-page applications in AngularJS, it’s common to display different partial views based on the route or state. Often, you’ll want your application’s header (whether that’s the <title> tag, a navigation bar, or a header <div>) to change dynamically depending on which partial is currently being shown. Below are a few ways to achieve this.

1. Change the Page <title> Dynamically

If by “header” you mean the HTML page title (in the <head> section), you can set it in your route configuration and update it whenever the route changes.

Step 1: Add a Title Property in Your Route Configuration

For ngRoute:

angular.module('myApp', ['ngRoute']) .config(function($routeProvider) { $routeProvider .when('/home', { templateUrl: 'views/home.html', controller: 'HomeController', // Custom property for the page title title: 'Home Page' }) .when('/about', { templateUrl: 'views/about.html', controller: 'AboutController', title: 'About Us' }) .otherwise({ redirectTo: '/home' }); });

Step 2: Listen for $routeChangeSuccess and Update $rootScope Title

You can update $rootScope.pageTitle on each route change and then bind it in your main index.html.

angular.module('myApp') .run(function($rootScope, $route) { $rootScope.$on('$routeChangeSuccess', function(event, current) { // current might be undefined if no matching route if (current.$$route && current.$$route.title) { $rootScope.pageTitle = current.$$route.title; } else { $rootScope.pageTitle = 'Default Title'; } }); });

Step 3: Bind the Title in Your index.html

<!DOCTYPE html> <html ng-app="myApp"> <head> <title>{{ pageTitle }}</title> <!-- other head content --> </head> <body> <ng-view></ng-view> </body> </html>

Now, whenever you navigate to a new route, $rootScope.pageTitle updates based on the route’s custom property, and the <title> tag reflects that change.

2. Change a Navigation Bar or Header <div> Dynamically

If your “header” refers to a navigation bar or a top <div> in your layout, you can do something similar:

  1. Store the desired header text, icons, or styles in your route config or in a service.
  2. Listen to route change events.
  3. Update a $rootScope or a shared service property that your main layout controller watches.

Example Using $routeProvider

$routeProvider .when('/dashboard', { templateUrl: 'views/dashboard.html', controller: 'DashboardController', headerInfo: { title: 'Dashboard', icon: 'dashboard-icon.png' } }) .when('/profile', { templateUrl: 'views/profile.html', controller: 'ProfileController', headerInfo: { title: 'User Profile', icon: 'user-icon.png' } });

In your run block or a top-level controller, watch $routeChangeSuccess:

.run(function($rootScope) { $rootScope.$on('$routeChangeSuccess', function(event, current) { if (current.$$route && current.$$route.headerInfo) { $rootScope.headerTitle = current.$$route.headerInfo.title; $rootScope.headerIcon = current.$$route.headerInfo.icon; } else { $rootScope.headerTitle = 'My App'; $rootScope.headerIcon = 'default-icon.png'; } }); });

In your main layout (e.g., index.html or a root partial):

<header> <img ng-src="{{ headerIcon }}" alt="Header Icon"> <h1>{{ headerTitle }}</h1> </header> <ng-view></ng-view>

This way, each partial view can define how the header looks, and you only have one header element in the layout.

3. Using UI-Router (If You’re Not Using ngRoute)

If your project uses UI-Router (another popular router for AngularJS), the concept is similar but with states instead of $routeProvider. For each state, define custom data or a resolve property:

$stateProvider .state('home', { url: '/home', templateUrl: 'views/home.html', controller: 'HomeController', data: { headerTitle: 'Home Page', headerIcon: 'home-icon.png' } }) .state('about', { url: '/about', templateUrl: 'views/about.html', controller: 'AboutController', data: { headerTitle: 'About Us' } });

Then in a run block or a top-level controller:

.run(function($rootScope, $state) { $rootScope.$on('$stateChangeSuccess', function(event, toState) { if (toState.data && toState.data.headerTitle) { $rootScope.headerTitle = toState.data.headerTitle; $rootScope.headerIcon = toState.data.headerIcon || 'default-icon.png'; } else { $rootScope.headerTitle = 'My App'; $rootScope.headerIcon = 'default-icon.png'; } }); });

The <header> binding remains the same:

<header> <img ng-src="{{ headerIcon }}"> <h1>{{ headerTitle }}</h1> </header> <ui-view></ui-view> <!-- UI-Router's equivalent of <ng-view> -->

Best Practices

  1. Single Source of Truth
    Maintain the “header info” in the route config or UI-Router state so that each partial knows exactly how the header should look.

  2. Minimize Global Scope
    Use $rootScope sparingly (only if your header is truly global). If you have a layout controller, consider storing the header info there, and inject it into child views as needed.

  3. Avoid Repeated Elements
    Don’t duplicate <header> in every partial. Instead, keep one header in the layout (e.g., index.html), and let each partial define the data that modifies that header.

  4. Fallbacks
    Provide fallback values (like 'My App', a default icon, etc.) so if a route does not define custom header data, the UI remains consistent.

Going Beyond: Mastering AngularJS & System Design

Setting up a dynamic header is just one piece of building a robust single-page application in AngularJS. To deepen your expertise, check out the following resources from DesignGurus.io:

If you’d like personalized feedback from ex-FAANG engineers, check out:

And for free tutorials, visit the DesignGurus.io YouTube channel.

Final Thoughts

To dynamically change the header based on which AngularJS partial view is displayed:

  1. Attach data (like a title or icon) to each route/state.
  2. Listen for route/state changes in a run block or layout controller.
  3. Update a shared property (e.g., $rootScope.headerTitle) used by your main header.

By keeping your header in one place (e.g., index.html or a root component) and letting each partial define its own header data, you maintain a clean, modular design that’s easy to update as your AngularJS app evolves.

CONTRIBUTOR
TechGrind