Comment et où utiliser :: ng-deep?

90

Je suis nouveau dans Angular 4, alors quelqu'un pourrait-il expliquer comment et où l'utiliser ::ng-deepdans Angular 4?

En fait, je veux écraser certaines des propriétés CSS des composants enfants des composants parents. De plus, est-il pris en charge sur IE11?

Jeyabalan Thavamani
la source
Depuis /deep/et ::ng-deepsont tous deux obsolètes, je vous suggère de consulter cette réponse stackoverflow.com/a/49308475/2275011 et de commenter pour plus de détails et de solutions.
Ferie

Réponses:

92

Généralement, le /deep/ “shadow-piercing”combinateur peut être utilisé pour forcer un style à child components. Ce sélecteur avait un alias >>> et en a maintenant un autre appelé :: ng-deep.

depuis /deep/ combinatorest obsolète, il est recommandé d'utiliser::ng-deep

Par exemple:

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

et css

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

il sera appliqué aux composants enfants

Sajeetharan
la source
S'agit-il d'un support pour IE11?
Jeyabalan Thavamani
2
Angular en fait l'analyse - vous n'avez donc pas à vous soucier de la compatibilité.
Simon_Weaver
est-ce uniquement pour les composants enfants? comme je me souviens et comme je le vois dans un autre commentaire, c'est également pour les éléments dom en dehors du composant.
yaya
Je peux confirmer qu'il fait aussi des composants parents ... J'ai juste eu le cas et j'étais ennuyé par cela.
Shadoweb
1
Génial, cela a parfaitement fonctionné.
Alfredo Zamudio
70

USAGE

::ng-deep, >>>et /deep/désactivez l'encapsulation de vue pour des règles CSS spécifiques, en d'autres termes, cela vous donne accès aux éléments DOM, qui ne sont pas dans le HTML de votre composant. Par exemple, si vous utilisez Angular Material (ou toute autre bibliothèque tierce comme celle-ci), certains éléments générés sont en dehors de la zone de votre composant (comme la boîte de dialogue ) et vous ne pouvez pas accéder à ces éléments directement ou en utilisant un CSS standard façon. Si vous souhaitez modifier les styles de ces éléments, vous pouvez utiliser l'une de ces trois choses, par exemple:

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

Pour l' instant , l' équipe angulaire recommande de faire « profonds » manipulations uniquement avec émulé encapsulation vue.

DÉSAPPROBATION

Les manipulations "profondes" sont en fait obsolètes aussi, MAIS cela fonctionne toujours pour le moment, car Angular prend en charge le pré-traitement (ne vous précipitez pas pour refuser ::ng-deepaujourd'hui, jetez d'abord un coup d'œil aux pratiques de dépréciation ).

Quoi qu'il en soit, avant de suivre cette voie, je vous recommande de jeter un œil à la désactivation de l' approche d' encapsulation de vue (ce qui n'est pas non plus idéal, cela permet à vos styles de s'infiltrer dans d'autres composants), mais dans certains cas, c'est un meilleur moyen. Si vous avez décidé de désactiver l'encapsulation des vues, il est fortement recommandé d'utiliser des classes spécifiques pour éviter l'intersection des règles CSS, et enfin, éviter un désordre dans vos feuilles de style. Il est vraiment facile de désactiver directement dans le .tsfichier du composant :

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

Vous pouvez trouver plus d'informations sur l'encapsulation des vues dans cet article.

Suicide commercial
la source
3
La désactivation de l'encapsulation de vue applique tous les CSS de votre composant globalement.
Vedran
16
N'utilisez pas ViewEncapsulation.None! Cela causera beaucoup de dégâts en permettant à ces styles de s'infiltrer dans d'autres composants.
Alex Klaus
1
@AlexKlaus, d'accord, c'est pourquoi j'ai mentionné dans la réponse que ce n'est pas idéal. En fait, je ne l'ai utilisé qu'une seule fois pour appliquer des styles répétables partagés aux composants de matériau angulaire. Si vous essayez de désactiver l'encapsulation, vous risquez d'obtenir un désordre à un moment donné. Il est bon de connaître cette option, mais ne l'utilisez pas tant que vous n'êtes pas absolument sûr d'en avoir besoin.
Commercial Suicide
29

Je voudrais souligner l'importance de limiter les ::ng-deepaux seuls enfants d'un composant en exigeant que le parent soit une classe css encapsulée.

Pour que cela fonctionne, il est important d'utiliser ::ng-deepaprès le parent, pas avant sinon cela s'appliquerait à toutes les classes avec le même nom au moment où le composant est chargé.

Composant css:

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

Modèle de composant:

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

CSS résultant (généré angulaire):

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

ÉDITER:

Vous pouvez obtenir le même comportement en utilisant le :hostmot - clé au lieu de créer une nouvelle classe css.

:host ::ng-deep .mat-checkbox-layout
Vedran
la source
5
mec, ta réponse my-component ::ng-deep...vient de sauver ma journée. J'ai passé toute la journée à essayer d'appliquer un style à mon composant avec ng-deep et je remplaçais tous mes composants, de toute mon application.
Cristiano Bombazar
2
A noter: "Afin d'étendre le style spécifié au composant actuel et à tous ses descendants [mais pas globalement], assurez-vous d'inclure le: host selector before :: ng-deep." De: angular.io/guide/component-styles
StvnBrkdll
1
@CristianoBombazar - vous obtiendrez le même comportement avec le :hostmot-clé - a ajouté une note à la réponse pour plus de clarté.
Vedran
23

Assurez-vous de ne pas manquer l'explication :host-contextqui se trouve directement au-dessus ::ng-deepdans le guide angulaire: https://angular.io/guide/component-styles . Avertissement: je l'ai manqué jusqu'à maintenant et j'aurais aimé le voir plus tôt.

::ng-deepest souvent nécessaire lorsque vous n'avez pas écrit le composant et n'avez pas accès à sa source, mais :host-contextpeut être une option très utile lorsque vous le faites.

Par exemple, j'ai un en- <h1>tête noir à l' intérieur d'un composant que j'ai conçu et je souhaite pouvoir le changer en blanc lorsqu'il est affiché sur un arrière-plan à thème sombre.

Si je n'avais pas accès à la source, je devrai peut-être le faire dans le css pour le parent:

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

Mais à la place, :host-contextvous pouvez le faire à l' intérieur du composant.

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

Cela cherchera n'importe où dans la chaîne de composants .theme-darket appliquera le css au h1 s'il est trouvé. C'est une bonne alternative au fait de trop compter sur ::ng-deepce qui, bien que souvent nécessaire, est en quelque sorte un anti-modèle.

Dans ce cas, le &est remplacé par le h1(c'est ainsi que sass / scss fonctionne) afin que vous puissiez définir votre css «normal» et thématique / alternatif juste à côté de l'autre, ce qui est très pratique.

Veillez à obtenir le nombre correct de fichiers :. Car ::ng-deepil y en a deux et pour :host-contextun seul.

Simon_Weaver
la source
Vous pouvez également l'utiliser :host(.theme-dark)si vous ne souhaitez hériter theme-darkd'aucun composant parent. Cela dépendra entièrement de la conception css de votre site. De plus, les attributs peuvent être très utiles et peuvent être combinés de manière sophistiquée en css seul:host([theme='dark']:not([dayofweek='tuesday'))
Simon_Weaver
Notez également que cela suit les règles css normales, donc si vous avez un composant tel que décrit ci-dessus (avec css de contexte hôte) à l'intérieur d'un conteneur qui a une .theme-lightclasse, celui-ci est à son tour imbriqué dans un conteneur avec .theme-darkil reprendra theme-darket appliquera le css. Mais c'est une excellente solution pour les classes de type 'modernizr', ou si vous avez un thème défini globalement et une seule fois.
Simon_Weaver
Puis-je utiliser: host-context au lieu de :: ng-deep?
eddy le
@eddy Je suis trop somnolent en ce moment pour y réfléchir complètement, mais le contexte hôte est presque comme ng-deep mais monte dans l'arborescence DOM au lieu de descendre. Donc, ce n'est absolument pas équivalent, mais vous pourriez
Simon_Weaver
2

Juste une mise à jour:

Vous devriez utiliser ::ng-deepau lieu de /deep/qui semble être obsolète.

Par documentation:

Le combinateur descendant qui perce les ombres est obsolète et la prise en charge est supprimée des principaux navigateurs et outils. En tant que tel, nous prévoyons de supprimer le support dans Angular (pour les 3 de / deep /, >>> et :: ng-deep). Jusque-là, :: ng-deep devrait être préféré pour une compatibilité plus large avec les outils.

Vous pouvez le trouver ici

Balázs Takács
la source
5
Dans ce texte, il est clairement indiqué que :: ng-deep est également obsolète: "nous prévoyons de supprimer le support dans Angular (pour les 3 de / deep /, >>> et :: ng-deep)".
adripanico
-2

Utilisez :: ng-deep avec précaution. Je l'ai utilisé tout au long de mon application pour définir la couleur de la barre d'outils de conception de matériaux sur différentes couleurs dans mon application uniquement pour constater que lorsque l'application testait les couleurs de la barre d'outils les unes sur les autres. Venez découvrir que c'est parce que ces styles deviennent globaux, voir cet article Voici une solution de code fonctionnelle qui ne se répand pas dans les autres composants.

<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
la source