htmlangulartypescriptfrontendsingle-page-application

How to bind a dynamic value to index.html file content in Angular?


I have a simple web application which is developed by Angular 18. I am going to bind a dynamic attribute to the <html> tag in the index.html file as follows:

<!doctype html>
<html lang="en" class="h-100" [data-bs-theme]="theme">
<head>
  <meta charset="utf-8">
  <title>My app</title>
  <base href="/">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body class="h-100">
  <app-root></app-root>
</body>
</html>

I tried to define the theme property in the main.ts and app.component.ts files but it does not work!

Is it possible to do that? Where can I define and programmatically change the theme property? What is the best practice to meet this requirement?


Solution

  • You can get the HTML element using document.querySelector and set the value manually.

    The reason you are not getting the variable updated, is because all the content inside the app-root is where the angular application exists, so only inside this scope the bindings work. Hence the body and HTML tags do not have any working angular functionality.

    main.ts

    import { Component } from '@angular/core';
    import { bootstrapApplication } from '@angular/platform-browser';
    
    @Component({
      selector: 'app-root',
      standalone: true,
      template: `
        <h1>Hello from {{ name }}!</h1>
        <a target="_blank" href="https://angular.dev/overview">
          Learn more about Angular
        </a>
    
        <button (click)="changeBsValue('dark')"> change theme </button>
      `,
    })
    export class App {
      name = 'Angular';
    
      ngOnInit() {
        this.changeBsValue('light');
      }
    
      changeBsValue(value: string) {
        const html = document.querySelector('html');
        html!.setAttribute('data-bs-theme', value);
      }
    }
    
    bootstrapApplication(App);
    

    index.html

    <!DOCTYPE html>
    <html lang="en" [data-bs-theme]="''">
      <head>
        <title>My app</title>
        <meta charset="UTF-8" />
        <base href="/" />
      </head>
      <body>
        <app-root>Loading...</app-root>
      </body>
    </html>
    

    styles.scss

    /* Add application styles & imports to this file! */
    html[data-bs-theme='light'] h1 {
      background-color: red;
    }
    
    html[data-bs-theme='dark'] h1 {
      background-color: black;
      color: white;
    }
    

    Stackblitz Demo