16

I have three components. These are HomeComponent, SignInComponent and AppComponent. My Home Page (HomeComponent) is showing when the application opened. I clicked the "Sign In" button by signin page opens.I want "signin-page" class to body while opening it.

How can I do it?

// AppComponent
import { Component } from '@angular/core';

@Component({
  moduleId: module.id,
  selector: 'app',
  template: '<router-outlet></router-outlet>'
})
export class AppComponent {}

// SignInComponent
import { Component } from '@angular/core';

@Component({
    moduleId: module.id,
    selector: 'signin',
    templateUrl: './signin.component.html',
    styleUrls: ['./signin.component.css']
})
export class SignInComponent {}

// HomeComponent
import { Component } from '@angular/core';

@Component({
    moduleId: module.id,
    selector: 'home',
    templateUrl: './home.component.html'
})
export class HomeComponent { }

// Part of index.html
<body>
<app>
    <div class="spinner">
        <div class="bounce1"></div>
        <div class="bounce2"></div>
        <div class="bounce3"></div>
    </div>
</app>
</body>
Mr.Ayanlar
  • 450
  • 1
  • 6
  • 12
  • I guess it would be much easier if you give every component container that will have dynamic class. Then you can add it really easily... – Dawid Zbiński Oct 11 '16 at 06:58

4 Answers4

23

You can change your root selector to body and then use HostBinding decorator

@Component({
  selector: 'body',
  template: `<child></child>`
})
export class AppComponent {
  @HostBinding('class') public cssClass = 'class1';
}

@Component({
  selector: 'child',
  template: `<button (click)="setClass()">Set class</button>`
})
export class ChildComponent {
  constructor(private rootComp: AppComponent) {  }
  setClass() {
    this.rootComp.cssClass = 'class2';
  }
}
yurzui
  • 205,937
  • 32
  • 433
  • 399
9
  1. If part of your application is in Angular, then you can do this:
let body = document.getElementsByTagName('body')[0];
body.classList.remove("className");   //remove the class
body.classList.add("className");   //add the class
  1. I'll prefer answer given by @Yurzui if the whole frontend is in Angular.
ssuperczynski
  • 3,190
  • 3
  • 44
  • 61
Rahul Singh
  • 150
  • 1
  • 7
8

Angular2 doesn't provide any built in way to modify DOM elements outside the root component (except the <title>).

querySelector('body').classList.add('signin-page');
querySelector('body').classList.remove('signin-page');

or

@Component(
  selector: 'body',
  templateUrl: 'app_element.html'
)
class AppElement {
  @HostBinding('class.fixed') 
  bool isFixed = true;
}

See also

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • This will break server side rendering. – Spock Apr 20 '17 at 08:40
  • @Günter Zöchbauer I'm using `@hostbinding` as you are here but my CSS triggers for a split second regardless of the boolean. – Ben Racicot Jul 25 '17 at 18:25
  • @BenRacicot what does "triggers for a split second" mean exactly. Can't imagine that it does anything but adding the class. – Günter Zöchbauer Jul 25 '17 at 18:47
  • @GünterZöchbauer I'm adding an active class to body whenever my bool is true. However the css for `.active` triggers whenever the app loads and goes away immediately afterwards. When I remove `@HostBinding('class') private page = 'active';` the css is not triggered. Just stumped. – Ben Racicot Jul 25 '17 at 19:04
  • Binding to `class` can be brittle and it's something different than binding to `class.active`. Perhaps you can reproduce in Plunker? – Günter Zöchbauer Jul 25 '17 at 19:19
1

Simple you can do this to add a class to body

document.body.classList.add('signin-page');
Amaldev ps
  • 257
  • 2
  • 12