1,993 Views

Ionic App Changing Themes at Runtime

Ionic App Changing Themes at Runtime

Using themes we can change the styling of different parts of our Ionic app. What if we want to chane the theme at runtime? Like toggling our app for day and night mode or changing theme according to users’ preference.
In our Ionic app, we cannot change the selected theme at runtime so we apply a different approach.
In this tutorial we will

  1. Create and prepare blank app
  2. Create two themes files light and dark
  3. Create a provider to get and set active theme
  4. Add ability to toggling active theme
  5. Apply theme to individual components
  6. Conclusion

We can’t change the selected theme of our Ionic app at runtime, so we need to become a bit more creative. In this tutorial we will see how to quickly change the styling of our app during runtime.

1. Create and prepare blank app

We start as always with blank Ionic app and generate a provider which will be used later to tell us which theme is currently used. Go ahead and run:

Start our Dynamic theming app

ionic start IonDynamicTheming blank
cd IonDynamicTheming
ionic g provider settings 

2. Create theme files

Now inside our app we need to create 2 files inside the src/theme folder, as these will reflect how our different themes will look like. Call the first file theme.light.scss and insert:

The light theme

.light-theme {
  ion-content {
    background-color: #fff;
  }
 
  .toolbar-background {
    background-color: #fff;
  }
}

The second one is called theme.dark.scss and you can insert this:

.dark-theme {
  ion-content {
    background-color: #090f2f;
    color: #fff;
  }
 
  .toolbar-title {
    color: #fff;
  }
 
  .header .toolbar-background {
    border-color: #ff0fff;
    background-color: #090f2f;
  }
}

Now we got 2 styling files which define some CSS classes for either a light or a dark theme. We also need to make them available, so put these import statements somewhere in your src/theme/variables.scss:

Import theme sytles to variables.scss

@import "theme.light";
@import "theme.dark";

We have now created and imported our themes, but as the class is never added those stylings will never be applied. So that’s where our route is taking us soon.

3. Create a provider to get and set active theme

But before we get there we need to implement our helper provider. The provider holds the active theme, and allows us to grab or set the active theme.

For this we use BehaviourSubject a special kind of object that inherits from Subject and Observable. Using this approach we can set a start value which will be emitted to all subscribers at first subscription and we can call next() to update value and all subscribers will immediately get the new value.

Open src/providers/settings/settings.ts and insert:

Implement the App Settings provider

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs/Rx';
 
@Injectable()
export class SettingsProvider {
 
    private theme: BehaviorSubject<String>;
 
    constructor() {
        this.theme = new BehaviorSubject('dark-theme');
    }
 
    setActiveTheme(val) {
        this.theme.next(val);
    }
 
    get activeTheme() {
        return this.theme.asObservable();
    }
}

Now we can change the theme from everywhere inside our app and the subscribers will be notified about the new value so we can change it accordingly.

4. Ability to toggle our theme

To toggle our app theme, we will add a simple button and toggle function to our page. We also subscribe to the current value and always update our variable inside the class once a new value comes to us in the subscribe() block.

Open src/pages/home/home.ts and insert:

import { SettingsProvider } from './../../providers/settings/settings';
import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
 
@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {
  selectedTheme: String;
 
  constructor(public navCtrl: NavController, private settings: SettingsProvider) {
    this.settings.getActiveTheme().subscribe(val => this.selectedTheme = val);
  }
 
    toggleAppTheme() {
    if (this.selectedTheme === 'dark-theme') {
      this.settings.setActiveTheme('light-theme');
    } else {
      this.settings.setActiveTheme('dark-theme');
    }
  }
 
}

Now we need to craft a little view around this and add the button to toggle our styling. Nothing really fancy here, so open src/pages/home/home.html and change it to:

The view of our simple app

<ion-header>
  <ion-navbar>
    <ion-title>
      Night & Day
    </ion-title>
  </ion-navbar>
</ion-header>
 
<ion-content padding>
  <p text-center>I shine at night and glow at day.</p>
  <button ion-button full icon-left (click)="toggleAppTheme()">
    <ion-icon  name="bulb"></ion-icon>Toggle Theme
  </button>
</ion-content>

We are now able to toggle our style, but nothing happens!

Well because the most important part is still missing, because we are currently just updating a random variable of a provider but we never really use it.

Adding the final Piece of Magic

This brings us to the last missing piece of our theming. The trick we use is apply the selected theme as a class to the root component of our app!

Therefore, we need to also subscribe to the value like we did before inside our src/app/app.component.ts like this:

Subscribe to changes at top level (our src/app/app.component.ts)

import { SettingsProvider } from './../providers/settings/settings';
import { Component } from '@angular/core';
import { Platform } from 'ionic-angular';
import { StatusBar } from '@ionic-native/status-bar';
import { SplashScreen } from '@ionic-native/splash-screen';
 
import { HomePage } from '../pages/home/home';
@Component({
  templateUrl: 'app.html'
})
export class MyApp {
  rootPage:any = HomePage;
  selectedTheme: String;
  
  constructor(platform: Platform, statusBar: StatusBar, splashScreen: SplashScreen, private settings: SettingsProvider) {
    this.settings.getActiveTheme().subscribe(val => this.selectedTheme = val);
 
    platform.ready().then(() => {
      statusBar.styleDefault();
      splashScreen.hide();
    });
  }
}

There is always a HTML file connected to this root component, and this is the place where we add the class using the Angular way of dynamically adding a class.

Open src/app/app.html and add it like this:

<ion-nav [root]="rootPage" [class]="selectedTheme"></ion-nav>

Now whenever we change our variable inside the provider (through our toggle) the new theme will be set.

5. Apply theme to individual components

We can do more and add theme related styles to each components instead of adding global styles. We will learn this by adding a card component in home page and styling it according to theme.

Open your src/app/pages/home/home.html an change it like this

<ion-header>
  <ion-navbar>
    <ion-title>
      Night & Day
    </ion-title>
  </ion-navbar>
</ion-header>
 
<ion-content padding>
  <p text-center>I shine at night and glow at day.</p>
  <button ion-button full icon-left (click)="toggleAppTheme()">
    <ion-icon  name="bulb"></ion-icon>Toggle Theme
  </button>
  <ion-card>
    <ion-card-content>Hello card</ion-card-content>
  </ion-card>
</ion-content>

Here, we just added a card component.

Open src/app/pages/home/home.scss and change it like this

.dark-theme{
    page-home {
        ion-card{
            background-color: #090f2f;
        }
    }
}
.light-theme{
    page-home{
        ion-card{
            background-color: #ffffff;
        }
    }
}

This styles the card component according the theme selected. We have just changed the background color of the card component. We can make any changes we like. And the changes will be applied according to the theme selected.

6. Conclusing

We could now add even more themes and toggle them dynamically to change the UI of our Ionic app at runtime.
Of course, you can save the selected theme in storage and load it when app loads to save user preferences.

Inspired by Devdactic Tutorial

Related Posts

Advancde Ionic Components

If you are a Ionic developer, beginner or expert, you will love this project. Publicly being developed in github, ionic3-components repository hosts […]

This post is trending.

Setting up Ionic View for Testing Ionic App

Introduction Ionic View is by far the best thing Ionic framework provides. The problem with hybrid apps is that we need to […]

%d bloggers like this: