Come e dove usare :: ng-deep?


95

Sono nuovo in Angular 4, quindi qualcuno potrebbe spiegare come e dove usarlo ::ng-deepin Angular 4?

In realtà voglio sovrascrivere alcune delle proprietà CSS dei componenti figlio dai componenti padre. Inoltre è supportato su IE11?


Dal momento che /deep/e ::ng-deepsono entrambi deprecato, vi suggerisco di prendere alook a questa risposta stackoverflow.com/a/49308475/2275011 e commenti per ulteriori dettagli e soluzioni.
Ferie

Risposte:


99

Di solito il /deep/ “shadow-piercing”combinatore può essere utilizzato per forzare uno stile a child components. Questo selettore aveva un alias >>> e ora ne ha un altro chiamato :: ng-deep.

poiché /deep/ combinatorè stato deprecato, si consiglia di utilizzare::ng-deep

Per esempio:

<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;
            }
        }
    }
}

verrà applicato ai componenti figlio


Supporta IE11?
Jeyabalan Thavamani

2
Angular lo analizza, quindi non devi preoccuparti della compatibilità.
Simon_Weaver

è solo per i componenti figlio? come ricordo e come vedo in un altro commento, è anche per elementi dom esterni al componente.
yaya

Posso confermare che fa anche i componenti principali ... Avevo appena avuto il caso e ne sono rimasto infastidito.
Shadoweb

74

UTILIZZO

::ng-deep, >>>E /deep/vista disabilitare l'incapsulamento di regole CSS specifiche, in altre parole, consente di accedere a elementi DOM, che non sono in HTML del componente. Ad esempio, se stai utilizzando Angular Material (o qualsiasi altra libreria di terze parti come questa), alcuni elementi generati sono al di fuori dell'area del tuo componente (come la finestra di dialogo ) e non puoi accedere a quegli elementi direttamente o utilizzando un normale CSS modo. Se vuoi cambiare gli stili di quegli elementi, puoi usare una di queste tre cose, ad esempio:

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

Per ora il team di Angular consiglia di fare manipolazioni "profonde" solo con l' incapsulamento della vista EMULATO .

DEPRECAZIONE

anche le manipolazioni "profonde" sono in realtà deprecate , MA per ora funziona ancora, perché Angular supporta la pre-elaborazione (non affrettarti a rifiutare ::ng-deepoggi, dai un'occhiata a pratiche di deprecazione ).

Ad ogni modo, prima di seguire questo modo, ti consiglio di dare un'occhiata alla disabilitazione dell'approccio all'incapsulamento della vista (che non è nemmeno l'ideale, consente ai tuoi stili di trapelare in altri componenti), ma in alcuni casi è un modo migliore. Se hai deciso di disabilitare l'incapsulamento della vista, ti consigliamo vivamente di utilizzare classi specifiche per evitare l'intersezione delle regole CSS e, infine, evitare confusione nei fogli di stile. È davvero facile disabilitare direttamente nel .tsfile del componente :

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

Puoi trovare maggiori informazioni sull'incapsulamento della vista in questo articolo.


3
La disattivazione dell'incapsulamento della vista applica globalmente tutti i CSS nel componente.
Vedran

19
Non usare ViewEncapsulation.None! Farà molti danni rendendo possibile che questi stili penetrino in altri componenti.
Alex Klaus

1
@AlexKlaus, d'accordo, ecco perché ho detto nella risposta che non è l'ideale. In realtà, l'ho usato solo una volta per applicare stili ripetibili condivisi ai componenti di materiale angolare. Se provi a disabilitare l'incapsulamento, a un certo punto potresti avere un pasticcio. È utile conoscere questa opzione, ma non usarla se non sei assolutamente sicuro di averne bisogno.
Commercial Suicide

36

Vorrei sottolineare l'importanza di limitare gli ::ng-deepunici figli di un componente richiedendo che il genitore sia una classe CSS incapsulata.

Affinché funzioni è importante usare il ::ng-deepdopo il genitore, non prima altrimenti si applicherebbe a tutte le classi con lo stesso nome nel momento in cui il componente viene caricato.

Componente css:

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

Modello componente:

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

CSS risultante (generato angolare):

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

MODIFICARE:

È possibile ottenere lo stesso comportamento utilizzando la :hostparola chiave invece di creare una nuova classe CSS.

:host ::ng-deep .mat-checkbox-layout

7
amico, la tua risposta mi ha my-component ::ng-deep...appena salvato la giornata. Ho passato tutto il giorno a cercare di applicare uno stile per il mio componente con ng-deep e ho ignorato tutti i miei componenti, dalla mia intera applicazione.
Cristiano Bombazar

2
Vale la pena notare: "Per definire l'ambito dello stile specificato per il componente corrente e tutti i suoi discendenti [ma non globalmente], assicurati di includere: host selector prima di :: ng-deep." Da: angular.io/guide/component-styles
StvnBrkdll

1
@CristianoBombazar - otterrai lo stesso comportamento con la :hostparola chiave - ha aggiunto una nota alla risposta per chiarezza.
Vedran

25

Assicurati di non perdere la spiegazione di :host-contextcui è direttamente sopra ::ng-deepnella guida angolare: https://angular.io/guide/component-styles . Mi è mancato fino ad ora e vorrei averlo visto prima.

::ng-deepè spesso necessario quando non hai scritto il componente e non hai accesso ai suoi sorgenti, ma :host-contextpuò essere un'opzione molto utile quando lo fai.

Ad esempio, ho <h1>un'intestazione nera all'interno di un componente che ho progettato e voglio la possibilità di cambiarlo in bianco quando viene visualizzato su uno sfondo scuro a tema.

Se non ho avuto accesso alla fonte potrei doverlo fare nel css per il genitore:

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

Ma invece :host-contextpuoi farlo all'interno del 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
     }
 }

Questo cercherà ovunque nella catena dei componenti .theme-darke applicherà il css a h1 se trovato. Questa è una buona alternativa al fare troppo affidamento su ciò ::ng-deepche, sebbene spesso necessario, è in qualche modo un anti-pattern.

In questo caso il &viene sostituito dalh1 (è così che funziona sass / scss) in modo da poter definire il tuo css "normale" e a tema / alternativo uno accanto all'altro, il che è molto utile.

Fare attenzione a ottenere il numero corretto di file :. Perché ::ng-deepce ne sono due e per :host-contextuno solo.


Puoi anche usarlo :host(.theme-dark)se non vuoi ereditare theme-darkda alcun componente padre. Questo dipenderà interamente dal design CSS del tuo sito. Anche gli attributi possono essere molto utili e possono essere combinati in modi sofisticati solo in CSS:host([theme='dark']:not([dayofweek='tuesday'))
Simon_Weaver

Si noti inoltre che questo segue le normali regole CSS, quindi se si dispone di un componente come descritto sopra (con CSS contesto host) all'interno di un contenitore che ha una .theme-lightclasse, questa è a sua volta annidata all'interno di un contenitore con .theme-darkesso raccoglierà theme-darke applicherà il css. Ma questa è un'ottima soluzione per le classi di tipo "modernizr" o se hai un tema impostato a livello globale e solo una volta.
Simon_Weaver

Posso usare: host-context invece di :: ng-deep?
Eddy

@eddy Sono troppo assonnato in questo momento per pensarci bene, ma il contesto dell'host è quasi come ng-deep ma salendo sull'albero DOM invece che verso il basso. Quindi non è assolutamente equivalente, ma potresti
Simon_Weaver

2

Solo un aggiornamento:

Dovresti usare ::ng-deepinvece di quello /deep/che sembra essere deprecato.

Per documentazione:

Il combinatore discendente che penetra nell'ombra è deprecato e il supporto è stato rimosso dai principali browser e strumenti. Pertanto, abbiamo in programma di eliminare il supporto in Angular (per tutti e 3 i di / deep /, >>> e :: ng-deep). Fino ad allora :: ng-deep dovrebbe essere preferito per una più ampia compatibilità con gli strumenti.

Puoi trovarlo qui


5
In questo testo si dice chiaramente che :: ng-deep è anche deprecato: "abbiamo in programma di eliminare il supporto in Angular (per tutti e 3 i di / deep /, >>> e :: ng-deep)".
adripanico

-2

Usa :: ng-deep con cautela. L'ho usato in tutta la mia app per impostare il colore della barra degli strumenti del material design su colori diversi in tutta la mia app solo per scoprire che quando l'app era in fase di test i colori della barra degli strumenti si sovrappongono. Vieni a scoprire che è perché questi stili diventano globali, vedi questo articolo Ecco una soluzione di codice funzionante che non si diffonde in altri componenti.

<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');
  }

}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.