Como e onde usar :: ng-deep?

95

Eu sou novo no Angular 4, então alguém poderia explicar como e onde usar ::ng-deepno Angular 4?

Na verdade, quero substituir algumas das propriedades CSS dos componentes filhos dos componentes pais. Além disso, é compatível com o IE11?

Jeyabalan Thavamani
fonte
Como /deep/e ::ng-deepestão obsoletos, sugiro que você leia esta resposta stackoverflow.com/a/49308475/2275011 e comentários para obter mais detalhes e soluções.
Ferie de

Respostas:

99

Normalmente, o /deep/ “shadow-piercing”combinador pode ser usado para forçar a redução de um estilo child components. Este seletor tinha um alias >>> e agora tem outro chamado :: ng-deep.

desde /deep/ combinatorque foi descontinuado, é recomendado usar::ng-deep

Por exemplo:

<div class="overview tab-pane" id="overview" role="tabpanel" [innerHTML]="project?.getContent( 'DETAILS')"></div>

e css

.overview {
    ::ng-deep {
        p {
            &:last-child {
                margin-bottom: 0;
            }
        }
    }
}

será aplicado a componentes filhos

Sajeetharan
fonte
É suporte para IE11?
Jeyabalan Thavamani
2
O Angular analisa isso - então você não precisa se preocupar com compatibilidade.
Simon_Weaver
é apenas para componentes filhos? como eu me lembro e como vejo em outro comentário, é também para elementos dom fora do componente.
yaya
Posso confirmar que ele faz os componentes pai também ... Acabei de ver o caso e fiquei irritado com isso.
Shadoweb
74

USO

::ng-deep, >>>e /deep/desabilita o encapsulamento de visualização para regras CSS específicas, em outras palavras, dá acesso a elementos DOM, que não estão no HTML do seu componente. Por exemplo, se você estiver usando Angular Material (ou qualquer outra biblioteca de terceiros como esta), alguns elementos gerados estão fora da área do seu componente (como a caixa de diálogo ) e você não pode acessar esses elementos diretamente ou usando um CSS regular caminho. Se quiser alterar os estilos desses elementos, você pode usar uma dessas três coisas, por exemplo:

::ng-deep .mat-dialog {
  /* styles here */
}

Por enquanto, a equipe Angular recomenda fazer manipulações "profundas" apenas com EMULADO encapsulamento de visualização .

DEPRECAÇÃO

manipulações "profundas" também estão obsoletas , MAS ainda funcionam por enquanto, porque o Angular oferece suporte de pré-processamento (não se apresse em recusar ::ng-deephoje, dê uma olhada nas práticas de suspensão primeiro).

De qualquer forma, antes de seguir este caminho, recomendo que você dê uma olhada em desabilitar a abordagem de encapsulamento de visão (o que também não é ideal, pois permite que seus estilos vazem para outros componentes), mas em alguns casos, é uma maneira melhor. Se você decidiu desabilitar o encapsulamento de visão, é altamente recomendável usar classes específicas para evitar a interseção de regras CSS e, finalmente, evitar uma bagunça em suas folhas de estilo. É realmente fácil desativar diretamente no .tsarquivo do componente :

@Component({
  selector: '',
  template: '',
  styles: [''],
  encapsulation: ViewEncapsulation.None  // Use to disable CSS Encapsulation for this component
})

Você pode encontrar mais informações sobre o encapsulamento de visualizações neste artigo.

Suicídio Comercial
fonte
3
Desativar o encapsulamento de visão aplica todos os CSS em seu componente globalmente.
Vedran
19
Não use ViewEncapsulation.None! Isso causará muitos danos ao possibilitar que esses estilos vazem para outros componentes.
Alex Klaus
1
@AlexKlaus, concordo, é por isso que mencionei na resposta, que não é o ideal. Na verdade, usei apenas uma vez para aplicar estilos repetíveis compartilhados aos componentes Angular Material. Se você tentar desabilitar o encapsulamento, provavelmente obterá uma bagunça em algum ponto. É bom saber sobre essa opção, mas não a use enquanto não tiver certeza absoluta de que precisa dela.
Suicídio Comercial
36

Eu enfatizaria a importância de limitar o ::ng-deepa apenas filhos de um componente, exigindo que o pai seja uma classe css encapsulada.

Para que isso funcione, é importante usar ::ng-deepdepois do pai, não antes, caso contrário, ele se aplicaria a todas as classes com o mesmo nome no momento em que o componente é carregado.

CSS do componente:

.my-component ::ng-deep .mat-checkbox-layout {
    background-color: aqua;
}

Modelo de componente:

<h1 class="my-component">
    <mat-checkbox ....></mat-checkbox>
</h1>

Css resultante (gerado angular):

.my-component[_ngcontent-c1] .mat-checkbox-layout {
    background-color: aqua;
}

EDITAR:

Você pode obter o mesmo comportamento usando a :hostpalavra - chave em vez de criar uma nova classe css.

:host ::ng-deep .mat-checkbox-layout
Vedran
fonte
7
cara, sua resposta my-component ::ng-deep...salvou meu dia. Passei o dia todo tentando aplicar um estilo ao meu componente com ng-deep e estava substituindo todos os meus componentes, de todo o meu aplicativo.
Cristiano Bombazar
2
Vale a pena observar: "Para definir o escopo do estilo especificado para o componente atual e todos os seus descendentes [mas não globalmente], certifique-se de incluir o seletor: host antes de :: ng-deep." De: angular.io/guide/component-styles
StvnBrkdll
1
@CristianoBombazar - você obterá o mesmo comportamento com a :hostpalavra-chave - adicionou uma nota à resposta para maior clareza.
Vedran
25

Certifique-se de não perder a explicação :host-contextque está diretamente acima ::ng-deepno guia angular: https://angular.io/guide/component-styles . Eu perdi isso até agora e gostaria de ter visto antes.

::ng-deepgeralmente é necessário quando você não escreveu o componente e não tem acesso ao seu código-fonte, mas :host-contextpode ser uma opção muito útil quando você o faz.

Por exemplo, tenho um <h1>cabeçalho preto dentro de um componente que projetei e quero poder alterá-lo para branco quando for exibido em um fundo de tema escuro.

Se eu não tivesse acesso à fonte, posso ter que fazer isso no css para o pai:

.theme-dark widget-box ::ng-deep h1 { color: white; }

Mas em vez disso, :host-contextvocê pode fazer isso dentro do componente.

 h1 
 {
     color: black;       // default color

     :host-context(.theme-dark) &
     {
         color: white;   // color for dark-theme
     }

     // OR set an attribute 'outside' with [attr.theme]="'dark'"

     :host-context([theme='dark']) &
     {
         color: white;   // color for dark-theme
     }
 }

Isso procurará em qualquer lugar na cadeia de componentes .theme-darke aplicará o css ao h1, se encontrado. Esta é uma boa alternativa para confiar demais no ::ng-deepque, embora muitas vezes necessário, é um tanto antipadrão.

Neste caso, o &é substituído peloh1 (é assim que funciona o sass / scss) para que você possa definir o seu css 'normal' e temático / alternativo um ao lado do outro, o que é muito útil.

Tenha cuidado para obter o número correto de :. Pois ::ng-deepexistem dois e :host-contextapenas um.

Simon_Weaver
fonte
Você também pode usar :host(.theme-dark)se não quiser herdar theme-darkde nenhum componente pai. Isso dependerá inteiramente do design de css do seu site. Além disso, os atributos podem ser muito úteis e podem ser combinados de maneiras sofisticadas apenas no css:host([theme='dark']:not([dayofweek='tuesday'))
Simon_Weaver
Observe também que isso segue as regras normais de css, então se você tiver um componente conforme descrito acima (com css de contexto de host) dentro de um contêiner que tem uma .theme-lightclasse que, por sua vez, está aninhada dentro de um contêiner com .theme-darkele ainda pegará o theme-darke aplicará o css. Mas esta é uma ótima solução para classes do tipo 'modernizr', ou se você tiver um tema definido globalmente e apenas uma vez.
Simon_Weaver
Posso usar: host-context em vez de :: ng-deep?
eddy
@eddy Estou com muito sono agora para pensar bem sobre isso, mas o contexto do host é quase como ng-deep, mas indo para CIMA da árvore DOM em vez de para baixo. Portanto, não é absolutamente equivalente, mas você poderia
Simon_Weaver
2

Apenas uma atualização:

Você deve usar em ::ng-deepvez de /deep/que parece estar obsoleto.

Por documentação:

O combinador descendente que perfura a sombra está obsoleto e o suporte está sendo removido dos principais navegadores e ferramentas. Como tal, planejamos deixar o suporte no Angular (para todos os 3 de / deep /, >>> e :: ng-deep). Até então, :: ng-deep deve ser preferido para uma compatibilidade mais ampla com as ferramentas.

Você pode encontrar aqui

Balázs Takács
fonte
5
Neste texto diz claramente que :: ng-deep também está obsoleto: "planejamos descartar o suporte em Angular (para todos os 3 de / deep /, >>> e :: ng-deep)".
adripanico
-2

Use :: ng-deep com cuidado. Usei-o em todo o meu aplicativo para definir a cor da barra de ferramentas do material design para cores diferentes em todo o meu aplicativo apenas para descobrir que quando o aplicativo estava testando as cores da barra de ferramentas pisavam umas nas outras. Venha descobrir que é porque esses estilos se tornam globais, consulte este artigo. Aqui está uma solução de código funcional que não penetra em outros componentes.

<mat-toolbar #subbar>
...
</mat-toolbar>

export class BypartSubBarComponent implements AfterViewInit {
  @ViewChild('subbar', { static: false }) subbar: MatToolbar;
  constructor(
    private renderer: Renderer2) { }
  ngAfterViewInit() {
    this.renderer.setStyle(
      this.subbar._elementRef.nativeElement, 'backgroundColor', 'red');
  }

}
Post Impatica
fonte