Customize the appearance of pages in Ionic 2 on the fly

In my app, there are 2 different themes based on the subject matter. However, some pages are shared between subjects. Therefore, I need to customize the ion-content based on the subject.

I am looking for a solution to allow page-test to switch between different ion-content styles.

@media only screen and (min-width : 600px) {
    .page-test {
        ion-content{
            background-image: url('../assets/mybkg.png');
            background-size: cover;
            color: black;
        }
    }

    @media only screen and (max-width : 599px) {
    .page-test {
        ion-content{
            background: #78d2ff;
            background: -moz-linear-gradient(top, #78d2ff 0%, #0080c0 100%);
            background: -webkit-linear-gradient(top, #78d2ff 0%, #0080c0 100%);
            background: linear-gradient(to bottom, #78d2ff 0%, #0080c0 100%);
            filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#78d2ff', endColorstr='#0080c0', GradientType=0);
            color: white;
        }
    }

Currently, I am creating duplicates of pages for different subjects which is not ideal as it involves duplicating HTML and code. This will make maintenance very difficult in the long run due to multiple similar situations.

Does anyone have suggestions on how to efficiently handle this issue?

Answer №1

After reading this informative article, you can implement a dynamic theming functionality in your Ionic app. With this demo, it is possible to dynamically change styles and show/hide specific parts of the view based on the selected theme.

1) Setting Up Themes

In the src/theme directory, create two new files: theme.light.scss and theme.dark.scss:

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

  .toolbar-background {
    background-color: #fff;
  }
}

And

// theme.dark.scss
// -----------------
.dark-theme {
  ion-content {
    background-color: #090f2f;
    color: #fff;
  }

  .toolbar-title {
    color: #fff;
  }

  .header .toolbar-background {
    border-color: #ff0fff;
    background-color: #090f2f;
  }
} 

Add the following lines to your src/theme/variables.scss file:

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

2) Implementing a Provider

Develop a SettingsProvider (

src/providers/settings/settings.ts
) to manage theme changes:

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);
    }

    getActiveTheme() {
        return this.theme.asObservable();
    }
}

Include the provider in the app.module.ts file:

@NgModule({
    declarations: [
        // ...
    ],
    imports: [
        // ...
    ],
    bootstrap: [IonicApp],
    entryComponents: [
        // ...
    ],
    providers: [
        // ...
        SettingsProvider
    ]
})
export class AppModule { }

3) Updating the AppComponent

Add the following code to your src/app/app.component.ts file:

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();
    });
  }
}

and in the view (src/app/app.html):

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

4) Changing the Theme

To switch between themes, utilize the SettingsProvider as shown below:

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');
    }
  }

}

Update the view with:

<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>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Oops! Property 'month' cannot be set on undefined value due to a TypeError

Despite not receiving any errors from Visual Studio Code, I’m encountering an error in Chrome's console. Below is the code snippet from my interfaces.ts file: export interface Data1{ month: string; employeeName: string; date: string; employmentSta ...

Navigating to a static html page using Angular version 6 or higher

I am working on an Angular project that consists of 3 components: country, region, and home. Currently, when I load the home page, the route is set up to point to HomeComponent, which includes hyperlinks for various routes. The application is behaving like ...

Sharing code between a node.js server and browser with Typescript: A step-by-step guide

I have an exciting project in mind to develop a multiplayer javascript game using a node.js server (with socket.io) and I am looking for a way to share code, specifically classes, between the web client and the server. Luckily, I came across this resource: ...

Adjusting the width of row items in Angular by modifying the CSS styles

I am envisioning a horizontal bar with items that are all the same width and evenly spaced apart. They can expand vertically as needed. Check out the updated version here on StackBlitz https://i.sstatic.net/MFfXd.png Issue: I am struggling to automatica ...

Issue with utilizing Lodash's _.findIndex method while installing lodash through tsd and saving it in an Angular2 project

I have successfully incorporated lodash in two different methods: Method 1: I installed it in bower_component and added declare var _:any; in components. It's working perfectly. Within a click event, I am calling this function: checkLodash() { _.f ...

Initiate npm start with CORS enabled

Currently, I am developing a small application using Angular2. Following the instructions provided in the 5min. Quickstart Guide, I used npm to install necessary modules and initiate a lite-server. However, my ultimate goal is to integrate this app into ...

Looping through an array using NgFor within an object

I've been working on pulling data from an API and displaying it on a webpage. Here is the JSON structure: {page: 1, results: Array(20), total_pages: 832, total_results: 16629} page: 1 results: Array(20) 0: adult: false backdrop_path: "/xDMIl84 ...

Eliminate any unnecessary padding from elements in angular2 components

Is there a way to remove the automatic padding added to new components in angular2? I am facing this issue with the header of my project, as shown in the image below: https://i.sstatic.net/25Zpn.png I attempted to eliminate the padding by setting it to 0 ...

Utilize React to iterate through an object using the .map

Help needed with fixing an eslint error that says Property 'date' does not exist on type 'never'. The issue seems to be related to data.date. Any suggestions on how to resolve this? import React from 'react' import app from & ...

Implementing an interface in TypeScript and assigning it a value using generics?

I'm struggling to make sense of a type declaration I came across in the react-router library: export interface RouteComponentProps< Params extends { [K in keyof Params]?: string } = {}, C extends StaticContext = StaticContext, S = H.Lo ...

The absence of a function implementation right after the declaration within a TypeScript class is a common issue that needs

I received a handwritten array to populate a table for my class, however I am now fetching this array's content from a JSON during the ngOnInit phase and it is not structured in the way I require. Therefore, I am attempting to create a function that ...

ERROR: Angular 5 encountered an issue in the common.js file at line 263 due to an undefined reference to $ st

After successfully running my Angular 5 project for a while, I suddenly encountered the following error in the console: Angular 5 common.js:263 Uncaught ReferenceError: $ st is not defined Surprisingly, the project continues to function properly despite t ...

How can I use Typescript to define a function that accepts a particular string as an argument and returns another specific string?

I've been working on this code snippet: const Locales = { en_gb: 'en-gb', en_us: 'en-us', } as const type ApiLocales = typeof Locales[keyof typeof Locales] type DatabaseLocales = keyof typeof Locales function databaseLanguage ...

Is it possible to declare language features in Typescript? For example, changing `!variable` to `no variable`

Can Typescript language features be declared within the app's source code? I want to enhance code clarity by implementing a small feature. Modified Null Test if (no userDetails) { // handle null } This new null test syntax is a little more conc ...

The parameter of type "Construct" cannot be assigned the argument of type "undefined"

I attempted to use code example from the AWS CDK documentation, but it did not function as I had anticipated. Using CDK version 2.62.2 with Typescript. In various parts of the code, a declaration error occurs stating that The argument of type "undefi ...

I am deciding between using CommonJS or ES module for my sub packages in a Yarn workspace for my Next.js project. Which one

Currently working on a Next.js monorepo project using TypeScript and yarn workspace. Within the yarn workspace, there are two packages: /web and /api. The /web package is a next.js project, while /api serves as a shared subpackage utilized by /web. /my-pr ...

Solving Issues with Names, Modules, and Other Strange Elements in Angular Universal

While the main app runs smoothly, attempting to serve the bundled SSR results in perplexing errors that I'm struggling to comprehend. All setup details are provided below for reference. The process of creating a server-side app seems riddled with sma ...

Importing JS files or SDKs in Angular that are not modules

Currently, I am incorporating the Avaya SDK (which consists of 3 JS files) into my Angular project. However, when attempting to import it, I encounter an error stating that it is not recognized as a module. Any suggestions on how to resolve this issue? Th ...

Encountering an issue with a specific property not being defined in a spec

I am currently developing an Angular8 project and have set up jest and jasmine for testing purposes. .ts // all necessary imports are included @Component({ selector: 'app-xyz', templateUrl: './xyz.component.html', styleUrls: [& ...

NativeScript is unable to locate any matching routes

I'm completely new to Angular and NativeScript, and I'm struggling with setting up routing. Whenever I try to navigate, I keep getting this error message: Error: Cannot match any routes. URL Segment: 'signIn' Here's the code sn ...