Angular2 dodaje klasę do tagu body

101

Jak mogę dodać klasę do tagu body bez tworzenia treści jako selektora aplikacji i używania powiązania hosta?

Próbowałem użyć Renderera, ale zmienia to całe ciało

Klasa wiązania Angular 2.x w tagu body

Pracuję nad dużą aplikacją angular2 i zmiana selektora głównego będzie miała wpływ na wiele kodu, będę musiał zmienić dużo kodu

Mój przypadek użycia jest następujący:

Kiedy otwieram komponent modalny (tworzony dynamicznie) chcę, aby pasek przewijania dokumentu był ukryty

Rachid O
źródło
1
Właściwie, jeśli pracujesz z js na stronie html, jaki jest problem z używaniem document.body.className|classList?
yurzui
haha gdyby to było takie proste :) ale to zła praktyka, aby uzyskać bezpośredni dostęp do dom
Rachid O
Możesz napisać duże opakowanie, które zostanie wykonane kilka sekund i na końcu dodane classdo body. Jeśli nie zamierzasz korzystać z renderowania serwera lub programu Web Worker, czego się boisz?
yurzui
więc nie ma lepszego rozwiązania niż to?
Rachid O
4
Nie mogę zrozumieć tych obraźliwych ludzi, którzy głosują przeciw i zamykają pytania bez ważnego powodu
Rachid O

Odpowiedzi:

218

Bardzo chciałbym to skomentować. Ale z powodu braku reputacji piszę odpowiedź. Cóż, znam dwie możliwości rozwiązania tego problemu.

  1. Wprowadź dokument globalny. Cóż, może to nie być najlepsza praktyka, ponieważ nie wiem, czy język ojczysty itp. To obsługuje. Ale jest to przynajmniej lepsze niż używanie czystego JS.
konstruktor (@Inject (DOCUMENT) prywatny dokument: Document) {}

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

Cóż, a może nawet lepiej. Możesz wstrzyknąć moduł renderujący lub moduł renderujący 2 (na NG4) i dodać klasę z mechanizmem renderującym.

export class myModalComponent implementuje OnDestroy {

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

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

EDYCJA DLA ANGULAR4:

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

export class myModalComponent implementuje OnDestroy {

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

  ngOnDestroy () {
    this.renderer.removeClass (document.body, 'modal-open');
  }
DaniS
źródło
3
dzięki za odpowiedź, myślę, że użycie rendrera jest najlepszym rozwiązaniem
Rachid O
6
Jeśli ktoś się zastanawia, skąd wziąć DOKUMENT, to jest:import { DOCUMENT } from '@angular/platform-browser'
Neph
15
Rozwiązanie Renderer jest znacznie lepsze. W Angular 4 Renderer został wycofany i zastąpiony przez Renderer2. Kod musiałby zmienić się na: this.renderer.addClass(document.body, 'modal-open'); ithis.renderer.removeClass(document.body, 'modal-open');
GreyBeardedGeek
3
Ponadto @Inject(DOCUMENT)nie jest już potrzebny w konstruktorze
GreyBeardedGeek
3
W ramach aktualizacji @Neph: importowanie DOCUMENT z przeglądarki platformy jest przestarzałe. Zamiast tego użyj @ angular / common.
Pieter De Bie
40

Myślę, że najlepszym sposobem na to jest połączenie obu podejść DaniSa powyżej: użycie renderera do faktycznego ustawienia / usunięcia klasy, ale także użycie wtryskiwacza dokumentów, więc nie jest silnie zależny od, window.documentale można go dynamicznie zastąpić (np. podczas renderowania po stronie serwera). Więc cały kod wyglądałby tak:

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
źródło
9
Dziękuję, dziękuję, dziękuję, dziękuję, dziękuję, dziękuję, dziękuję :)
Kamlesh