Angular2 ajoute une classe à la balise body

98

Comment puis-je ajouter une classe à la balise body sans faire du corps le sélecteur d'application et utiliser la liaison d'hôte?

J'ai essayé d'utiliser le Renderer mais ça change tout le corps

Classe de liaison angulaire 2.x sur balise body

Je travaille sur une grande application angular2 et changer le sélecteur racine aura un impact sur beaucoup de code, je devrai changer beaucoup de code

Mon cas d'utilisation est le suivant:

Lorsque j'ouvre un composant modal (créé dynamiquement), je veux que la barre de défilement du document se masque

Rachid O
la source
1
En fait, si vous travaillez avec js dans une page html, quel est le problème avec l'utilisation document.body.className|classList?
yurzui
haha si seulement c'était aussi simple :) mais c'est une mauvaise pratique d'accéder directement à dom
Rachid O
Vous pouvez écrire un grand emballage qui sera exécuté plusieurs secondes et à la fin ajoutée classà body. Si vous n'utilisez pas de rendu de serveur ou de Web Worker, de quoi avez-vous peur?
yurzui
il n'y a donc pas de meilleure solution que celle-ci?
Rachid O
4
Je ne peux pas comprendre ces personnes abusives qui votent contre et clôturent les questions sans raison valable
Rachid O

Réponses:

214

J'adorerais commenter. Mais à cause d'une réputation manquante, j'écris une réponse. Eh bien, je connais deux possibilités pour résoudre ce problème.

  1. Injectez le document global. Eh bien, ce n'est peut-être pas la meilleure pratique car je ne sais pas si nativescript, etc. prend en charge cela. Mais c'est au moins mieux que d'utiliser du JS pur.
constructeur (@Inject (DOCUMENT) document privé: Document) {}

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

Eh bien et peut-être même mieux. Vous pouvez injecter le moteur de rendu ou le moteur de rendu 2 (sur NG4) et ajouter la classe avec le moteur de rendu.

la classe d'exportation myModalComponent implémente OnDestroy {

  constructeur (moteur de rendu privé: Renderer) {
    this.renderer.setElementClass (document.body, 'modal-open', true);
   }

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

MODIFIER POUR ANGULAIRE4:

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

la classe d'exportation myModalComponent implémente OnDestroy {

  constructeur (moteur de rendu privé: Renderer2) {
    this.renderer.addClass (document.body, 'modal-open');
   }

  ngOnDestroy () {
    this.renderer.removeClass (document.body, 'modal-open');
  }
DaniS
la source
3
merci pour la réponse, je pense que l'utilisation du rendu est la meilleure solution
Rachid O
6
Au cas où quelqu'un se demanderait où obtenir le DOCUMENT, c'est:import { DOCUMENT } from '@angular/platform-browser'
Néph
14
La solution Renderer est bien meilleure. Dans Angular 4, Renderer a été abandonné et remplacé par Renderer2. Le code devrait changer en: this.renderer.addClass(document.body, 'modal-open'); etthis.renderer.removeClass(document.body, 'modal-open');
GreyBeardedGeek
3
En outre, @Inject(DOCUMENT)n'est plus nécessaire dans le constructeur
GreyBeardedGeek
3
En tant que mise à jour de @Neph: l'importation de DOCUMENT depuis le navigateur de la plateforme est obsolète. Utilisez plutôt @ angular / common.
Pieter De Bie
36

Je pense que la meilleure façon de le faire est une combinaison des deux approches de DaniS ci-dessus: utiliser le moteur de rendu pour définir / supprimer la classe, mais aussi utiliser l'injecteur de document, de sorte qu'il ne dépend pas fortement du window.documentmais qui peut être remplacé dynamiquement (par exemple lors du rendu côté serveur). Donc, tout le code ressemblerait à ceci:

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');
    }
}
DHainzl
la source
8
Merci, merci, merci, merci, merci, merci, merci :)
Kamlesh