Angular2 adiciona classe à tag do corpo

98

Como posso adicionar uma classe à tag do corpo sem tornar o corpo como o seletor de aplicativo e usando a vinculação do host?

Eu tentei usar o Renderer, mas mudou todo o corpo

Classe de vinculação Angular 2.x na tag do corpo

Estou trabalhando em um grande aplicativo angular2 e alterar o seletor de raiz impactará muito código, terei que alterar muito código

Meu caso de uso é este:

Quando eu abro um componente modal (criado dinamicamente), quero que a barra de rolagem do documento oculte

Rachid O
fonte
1
Na verdade, se você trabalha com js dentro da página html, qual é o problema em usar document.body.className|classList?
yurzui de
haha se fosse tão simples assim :) mas é uma má prática acessar o dom diretamente
Rachid O
Você pode escrever um grande wrapper que será executado vários segundo e no final adicionado classa body. Se você não vai usar renderização de servidor ou web worker, do que você tem medo?
yurzui de
então não há solução melhor do que essa?
Rachid O de
4
Não consigo entender essas pessoas abusivas que votam negativamente e fecham as perguntas sem nenhum motivo válido
Rachid O,

Respostas:

214

Eu adoraria comentar. Mas devido à falta de reputação, escrevo uma resposta. Bem, eu conheço duas possibilidades para resolver esse problema.

  1. Injete o documento global. Bem, pode não ser a melhor prática, pois não sei se o nativescript etc suporta isso. Mas é pelo menos melhor do que usar JS puro.
construtor (@Inject (DOCUMENT) documento privado: Documento) {}

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

Bem e talvez até melhor. Você pode injetar o renderizador ou o renderizador 2 (no NG4) e adicionar a classe com o renderizador.

export class myModalComponent implementa OnDestroy {

  construtor (renderizador privado: Renderer) {
    this.renderer.setElementClass (document.body, 'modal-open', true);
   }

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

EDITAR PARA ANGULAR4:

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

export class myModalComponent implementa OnDestroy {

  construtor (renderizador privado: Renderer2) {
    this.renderer.addClass (document.body, 'modal-open');
   }

  ngOnDestroy () {
    this.renderer.removeClass (document.body, 'modal-open');
  }
DaniS
fonte
3
obrigado pela resposta, acho que usar o rendrer é a melhor solução
Rachid O
6
Caso alguém esteja se perguntando onde conseguir o DOCUMENTO, é:import { DOCUMENT } from '@angular/platform-browser'
Neph
14
A solução Renderer é muito melhor. No Angular 4, o Renderer foi descontinuado e substituído pelo Renderer2. O código teria que mudar para: this.renderer.addClass(document.body, 'modal-open'); ethis.renderer.removeClass(document.body, 'modal-open');
GreyBeardedGeek
3
Além disso, @Inject(DOCUMENT)não é mais necessário no construtor
GreyBeardedGeek
3
Como uma atualização para @Neph: importar DOCUMENT do navegador da plataforma está obsoleto. Use @ angular / common.
Pieter De Bie
36

Acho que a melhor maneira de fazer isso é uma combinação de ambas as abordagens do DaniS acima: usando o renderizador para realmente definir / remover a classe, mas também usando o injetor de documentos, por isso não é fortemente dependente do, window.documentmas pode ser substituído dinamicamente (por exemplo, ao renderizar do lado do servidor). Portanto, todo o código ficaria assim:

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
fonte
8
Obrigado, obrigado, obrigado, obrigado, obrigado, obrigado, obrigado :)
Kamlesh