Estilo angular 2 - innerHTML

170

Estou recebendo pedaços de códigos HTML de chamadas HTTP. Coloco os blocos HTML em uma variável e insiro-os na minha página com [innerHTML], mas não consigo estilizar o bloco HTML inserido. Alguém tem alguma sugestão de como posso conseguir isso?

@Component({selector: 'calendar',
template: '<div [innerHTML]="calendar"></div>',
providers:[HomeService], 
styles: [` 
h3 {color:red;}
`})

O HTML que eu quero estilizar é o bloco contido na variável "calendário".

Jakob Svenningsson
fonte
Estilo de onde? De dentro do componente ou de estilos adicionados a index.html?
Günter Zöchbauer 28/03
como assim can not style the inserted HTML block? Mostre-nos o que você fez com um pequeno trecho de código.
28816 micronyks
Atualizei minha postagem com um trecho de código! :) obrigado
Jakob Svenningsson 28/03
1
Eu adicionei um link Plunker para a minha resposta
Günter Zöchbauer
@ GünterZöchbauer e se os códigos HTML tiverem CSS embutido? como será processado?
Iniravpatel

Respostas:

320

atualização 2 ::slotted

::slotted agora é suportado por todos os novos navegadores e pode ser usado com ViewEncapsulation.ShadowDom

https://developer.mozilla.org/en-US/docs/Web/CSS/::slotted

atualização 1 :: ng-deep

/deep/foi descontinuado e substituído por ::ng-deep.

::ng-deep também já está marcado como obsoleto, mas ainda não há substituição disponível.

Quando ViewEncapsulation.Nativefor adequadamente suportado por todos os navegadores e suportar estilo entre os limites do DOM da sombra, ::ng-deepprovavelmente será descontinuado.

original

Angular adiciona todos os tipos de classes CSS ao HTML que adiciona ao DOM para emular o encapsulamento CSS DOM de sombra para evitar estilos de sangramento dentro e fora dos componentes. Angular também reescreve o CSS adicionado para corresponder a essas classes adicionadas. Para HTML adicionado usando [innerHTML]essas classes, não são adicionados e o CSS reescrito não corresponde.

Como uma solução alternativa, tente

  • para CSS adicionado ao componente
/* :host /deep/ mySelector { */
:host ::ng-deep mySelector { 
  background-color: blue;
}
  • para CSS adicionado a index.html
/* body /deep/ mySelector { */
body ::ng-deep mySelector {
  background-color: green;
}

>>>(e o equivalente, /deep/mas /deep/funciona melhor com o SASS) e ::shadowforam adicionados no 2.0.0-beta.10. Eles são semelhantes aos combinadores de sombra DOM CSS (que foram descontinuados) e só funcionam com o encapsulation: ViewEncapsulation.Emulatedque é o padrão no Angular2. Eles provavelmente também trabalham com, ViewEncapsulation.Nonemas são ignorados apenas porque não são necessários. Esses combinadores são apenas uma solução intermediária até que recursos mais avançados para o estilo de componentes cruzados sejam suportados.

Outra abordagem é usar

@Component({
  ...
  encapsulation: ViewEncapsulation.None,
})

para todos os componentes que bloqueiam seu CSS (depende de onde você adiciona o CSS e de onde você deseja estilizar o HTML - podem ser todos os componentes em seu aplicativo)

Atualizar

Exemplo Plunker

Günter Zöchbauer
fonte
6
Apenas uma observação para qualquer pessoa, isso não funciona com o node-sass ou com o styleUrl. Somente nos estilos: [...]
thouliha
12
Com o uso do SASS em /deep/vez de>>>
Günter Zöchbauer
1
Você não pode ter diretivas ou componentes em conteúdo adicionado cominneeHTML
Günter Zöchbauer 8/17/17
1
Se o HTML fornecido pelo HTTP chamada é grande e tem css em linha como será isso possível, como eu não tenho os estilos pré-definidos, eu estou recebendo-lo do css em linha única @ GünterZöchbauer
iniravpatel
1
Guardou o dia no Angular 8! Thanx. É difícil acertar a pergunta para encontrar esta resposta!
Pianoman 21/06
12

A solução simples que você precisa seguir é

import { DomSanitizer } from '@angular/platform-browser';

constructor(private sanitizer: DomSanitizer){}

transformYourHtml(htmlTextWithStyle) {
    return this.sanitizer.bypassSecurityTrustHtml(htmlTextWithStyle);
}
Sahil Ralkar
fonte
2

Se você estiver tentando estilizar elementos HTML adicionados dinamicamente dentro de um componente Angular, isso pode ser útil:

// inside component class...

constructor(private hostRef: ElementRef) { }

getContentAttr(): string {
  const attrs = this.hostRef.nativeElement.attributes
  for (let i = 0, l = attrs.length; i < l; i++) {
    if (attrs[i].name.startsWith('_nghost-c')) {
      return `_ngcontent-c${attrs[i].name.substring(9)}`
    }
  }
}

ngAfterViewInit() {
  // dynamically add HTML element
  dynamicallyAddedHtmlElement.setAttribute(this.getContentAttr(), '')
}

Meu palpite é que não é garantido que a convenção para esse atributo seja estável entre as versões do Angular, para que se possa ter problemas com esta solução ao atualizar para uma nova versão do Angular (embora a atualização dessa solução provavelmente seja trivial nesse sentido. caso).

Trevor
fonte
2

Nós extraímos conteúdo frequentemente do nosso CMS como [innerHTML]="content.title". Colocamos as classes necessárias no styles.scssarquivo raiz do aplicativo e não no arquivo scss do componente. Nosso CMS elimina propositalmente estilos em linha, para que tenhamos preparado classes que o autor possa usar em seu conteúdo. Lembre-se de usar {{content.title}}o modelo não renderizará html a partir do conteúdo.

Lyfo
fonte
-3

Se você estiver usando o sass como pré-processador de estilo, poderá voltar ao compilador Sass nativo para dependência de dev:

npm install node-sass --save-dev

Para que você possa continuar usando / deep / para desenvolvimento.

Brian Lu
fonte