¿Cómo y dónde usar :: ng-deep?

90

Soy nuevo en Angular 4, así que, ¿alguien podría explicar cómo y dónde usarlo ::ng-deepen Angular 4?

En realidad, quiero sobrescribir algunas de las propiedades CSS de los componentes secundarios de los componentes principales. Además, ¿es compatible con IE11?

Jeyabalan Thavamani
fuente
Dado que /deep/y ::ng-deepestán en desuso, le sugiero que consulte esta respuesta stackoverflow.com/a/49308475/2275011 y comentarios para obtener más detalles y soluciones.
Ferie

Respuestas:

92

Por lo general, el /deep/ “shadow-piercing”combinador se puede usar para forzar un estilo a child components. Este selector tenía un alias >>> y ahora tiene otro llamado :: ng-deep.

ya que /deep/ combinatorha quedado obsoleto, se recomienda utilizar::ng-deep

Por ejemplo:

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

y css

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

se aplicará a los componentes secundarios

Sajeetharan
fuente
¿Es compatible con IE11?
Jeyabalan Thavamani
2
Angular lo analiza, por lo que no necesita preocuparse por la compatibilidad.
Simon_Weaver
¿es solo para componentes secundarios? como recuerdo y como veo en otro comentario, también es para elementos dom fuera del componente.
yaya
Puedo confirmar que también tiene componentes principales ... Acabo de tener el caso y eso me molestó.
Shadoweb
1
Impresionante, funcionó perfectamente.
Alfredo Zamudio
70

USO

::ng-deep, >>>Y la /deep/vista de encapsulación para desactivar las reglas CSS específicas, en otras palabras, que le da acceso a los elementos DOM, que no están en el HTML de su componente. Por ejemplo, si está usando Angular Material (o cualquier otra biblioteca de terceros como esta), algunos elementos generados están fuera del área de su componente (como el diálogo ) y no puede acceder a esos elementos directamente o usando un CSS normal camino. Si desea cambiar los estilos de esos elementos, puede usar una de esas tres cosas, por ejemplo:

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

Por ahora, el equipo de Angular recomienda realizar manipulaciones "profundas" solo con la encapsulación de vista EMULADA .

DEPRECACIÓN

Las manipulaciones "profundas" también están en desuso , PERO sigue funcionando por ahora, porque Angular admite el preprocesamiento (no se apresure a rechazarlo ::ng-deephoy, primero eche un vistazo a las prácticas de desuso ).

De todos modos, antes de seguir este camino, le recomiendo que eche un vistazo a la desactivación del enfoque de encapsulación de vistas (que tampoco es ideal, permite que sus estilos se filtren en otros componentes), pero en algunos casos, es una mejor manera. Si decidió deshabilitar la encapsulación de vista, se recomienda encarecidamente utilizar clases específicas para evitar la intersección de reglas CSS y, finalmente, evitar un desorden en sus hojas de estilo. Es realmente fácil de deshabilitar directamente en el .tsarchivo del componente :

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

Puede encontrar más información sobre la encapsulación de vistas en este artículo.

Suicidio comercial
fuente
3
Al deshabilitar la encapsulación de vistas, se aplica todo el CSS de su componente de forma global.
Vedran
16
¡No lo use ViewEncapsulation.None! Hará mucho daño al permitir que esos estilos se filtren en otros componentes.
Alex Klaus
1
@AlexKlaus, de acuerdo, por eso mencioné en la respuesta que no es ideal. En realidad, lo usé solo una vez para aplicar estilos repetibles compartidos a componentes de material angular. Si intenta deshabilitar la encapsulación, es posible que en algún momento se produzca un desastre. Es bueno conocer esta opción, pero no la use si no está absolutamente seguro de que la necesite.
Suicidio comercial
29

Destacaría la importancia de limitar ::ng-deepa los hijos únicos de un componente al exigir que el padre sea una clase CSS encapsulada.

Para que esto funcione, es importante usar ::ng-deepdespués del padre, no antes, de lo contrario se aplicaría a todas las clases con el mismo nombre en el momento en que se carga el componente.

CSS del componente:

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

Plantilla de componente:

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

CSS resultante (generado en ángulo):

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

EDITAR:

Puede lograr el mismo comportamiento utilizando la :hostpalabra clave en lugar de crear una nueva clase css.

:host ::ng-deep .mat-checkbox-layout
Vedrán
fuente
5
hombre, tu respuesta my-component ::ng-deep...acaba de salvarme el día. Pasé todo el día tratando de aplicar un estilo para mi componente con ng-deep y estaba anulando todos mis componentes, desde toda mi aplicación.
Cristiano Bombazar
2
Vale la pena señalar: "Para establecer el alcance del estilo especificado en el componente actual y todos sus descendientes [pero no globalmente], asegúrese de incluir el: selector de host antes de :: ng-deep". De: angular.io/guide/component-styles
StvnBrkdll
1
@CristianoBombazar: obtendrá el mismo comportamiento con la :hostpalabra clave: agregó una nota a la respuesta para mayor claridad.
Vedran
23

Asegúrese de no perderse la explicación :host-contextque se encuentra directamente arriba ::ng-deepen la guía angular: https://angular.io/guide/component-styles . Descargo de responsabilidad: me lo perdí hasta ahora y desearía haberlo visto antes.

::ng-deepa menudo es necesario cuando no escribiste el componente y no tienes acceso a su fuente, pero :host-contextpuede ser una opción muy útil cuando lo haces.

Por ejemplo, tengo un <h1>encabezado negro dentro de un componente que diseñé y quiero tener la capacidad de cambiarlo a blanco cuando se muestra sobre un fondo temático oscuro.

Si no tuve acceso a la fuente, es posible que tenga que hacer esto en el CSS para el padre:

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

Pero en cambio :host-context, puedes hacer esto dentro 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
     }
 }

Esto buscará en cualquier parte de la cadena de componentes .theme-darky aplicará el CSS al h1 si lo encuentra. Esta es una buena alternativa a confiar demasiado en lo ::ng-deepque, si bien a menudo es necesario, es algo así como un anti-patrón.

En este caso, &se reemplaza por h1(así es como funciona sass / scss) para que pueda definir su css 'normal' y temático / alternativo uno al lado del otro, lo cual es muy útil.

Tenga cuidado de obtener el número correcto de :. Porque ::ng-deephay dos y :host-contextsolo uno.

Simon_Weaver
fuente
También puede usarlo :host(.theme-dark)si no desea heredar theme-darkde ningún componente principal. Esto dependerá completamente del diseño CSS de su sitio. Además, los atributos pueden ser muy útiles y se pueden combinar de formas sofisticadas solo en CSS:host([theme='dark']:not([dayofweek='tuesday'))
Simon_Weaver
También tenga en cuenta que esto sigue las reglas normales de CSS, por lo que si tiene un componente como se describe anteriormente (con css de contexto de host) dentro de un contenedor que tiene una .theme-lightclase, esto a su vez está anidado dentro de un contenedor con el .theme-darkque todavía recogerá theme-darky aplicará el css. Pero esta es una gran solución para las clases de tipo 'modernizr', o si tiene un tema establecido globalmente y solo una vez.
Simon_Weaver
¿Puedo usar: host-context en lugar de :: ng-deep?
eddy
@eddy Tengo demasiado sueño en este momento para pensar completamente en esto, pero el contexto del host es casi como ng-deep pero subiendo el árbol DOM en lugar de hacia abajo. Entonces no es absolutamente equivalente, pero podrías
Simon_Weaver
2

Solo una actualización:

Debería usar en ::ng-deeplugar de lo /deep/que parece estar en desuso.

Por documentación:

El combinador descendiente que perfora las sombras está obsoleto y se está eliminando el soporte de los principales navegadores y herramientas. Como tal, planeamos eliminar el soporte en Angular (para los 3 de / deep /, >>> y :: ng-deep). Hasta entonces, se debería preferir :: ng-deep para una compatibilidad más amplia con las herramientas.

Lo puedes encontrar aqui

Balázs Takács
fuente
5
En este texto, dice claramente que :: ng-deep también está en desuso: "planeamos eliminar el soporte en Angular (para los 3 de / deep /, >>> y :: ng-deep)".
adripanico
-2

Utilice :: ng-deep con precaución. Lo usé en toda mi aplicación para configurar el color de la barra de herramientas de diseño de materiales en diferentes colores en toda mi aplicación solo para descubrir que cuando la aplicación estaba probando los colores de la barra de herramientas se superponen. Venga a descubrir que es porque estos estilos se vuelven globales, vea este artículo. Aquí hay una solución de código de trabajo que no se filtra en otros 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
fuente