ChatGPT解决这个技术问题 Extra ChatGPT

Angular2 add class to body tag

How can I add a class to the body tag without making the body as the app selector and using host binding?

I tried the using the Renderer but it changes the whole body

Angular 2.x bind class on body tag

I'm working on a big angular2 app and changing the root selector will impact a lot of code, I will have to change a lot of code

My use case is this:

When I open a modal component (created dynamically) I want the document scrollbar to hide

Actually if you work with js within html page what is the problem with using document.body.className|classList?
haha if only it was that simple :) but it's a bad practice to access dom directly
You can write a big wrapper that will be executed several second and at the end added class to body. If you are not going to use server rendering or web worker what you're afraid of?
so there's no better solution than this ?
I can't understand these abusive people who downvote and close questions for no valid reason

T
Tsvetan Ganev

I would love to comment. But due to missing reputation I write an answer. Well I know two possibilities to solve this issue.

Inject the Global Document. Well it might not be the best practice as I don't know if nativescript etc supports that. But it is at least better than use pure JS.

constructor(@Inject(DOCUMENT) private document: Document) {}

ngOnInit(){
   this.document.body.classList.add('test');
}

Well and perhaps even better. You could inject the renderer or renderer 2 (on NG4) and add the class with the renderer.

export class myModalComponent implements OnDestroy {

  constructor(private renderer: Renderer) {
    this.renderer.setElementClass(document.body, 'modal-open', true);
  }

  ngOnDestroy(): void {
    this.renderer.setElementClass(document.body, 'modal-open', false);
  }
}

EDIT FOR ANGULAR4:

import { Component, OnDestroy, Renderer2 } from '@angular/core';

export class myModalComponent implements OnDestroy {

  constructor(private renderer: Renderer2) {
    this.renderer.addClass(document.body, 'modal-open');
  }

  ngOnDestroy(): void {
    this.renderer.removeClass(document.body, 'modal-open');
  }
}

thanks for the reply, I think using the rendrer is the best solution
In case anyone wondering where to get DOCUMENT, that's: import { DOCUMENT } from '@angular/platform-browser'
The Renderer solution is much better. In Angular 4, Renderer has been deprecated and replaced with Renderer2. The code would have to change to: this.renderer.addClass(document.body, 'modal-open'); and this.renderer.removeClass(document.body, 'modal-open');
Also, @Inject(DOCUMENT) is no longer needed in the constructor
As an update to @Neph : importing DOCUMENT from platform-browser is deprecated. Use @angular/common instead.
D
DHainzl

I think the best way to do it is a combination of both approaches by DaniS above: Using the renderer to actually set / remove the class, but also using the document injector, so it is not strongly dependant on the window.document but that can be replaced dynamically (e.g. when rendering server-side). So the whole code would look like this:

import { DOCUMENT } from '@angular/common';
import { Component, Inject, OnDestroy, OnInit, Renderer2 } from '@angular/core';

@Component({ /* ... */ })
export class MyModalComponent implements OnInit, OnDestroy {
    constructor (
        @Inject(DOCUMENT) private document: Document,
        private renderer: Renderer2,
    ) { }

    ngOnInit(): void {
        this.renderer.addClass(this.document.body, 'embedded-body');
    }

    ngOnDestroy(): void {
        this.renderer.removeClass(this.document.body, 'embedded-body');
    }
}

This works great for adding a dark theme class to the body element!

关注公众号,不定期副业成功案例分享
Follow WeChat

Success story sharing

Want to stay one step ahead of the latest teleworks?

Subscribe Now