Angular Component styling — Using shadow piercing descendant selector
In this post, I am going to share how the shadow piercing descendant selector helped me with style scoping problem.
Well, I tried to create Angular wrapper for one of a JQuery
plugin. All worked as planned and later I noticed that I was not able to apply custom styles to the plugin in ViewEncapsulation.Emulated
mode. I can set the custom style when the ViewEncapsulation
is set to None
.
So I started to search for a solution to apply the custom style in ViewEncapsulation.Emulated
mode.
@Component({
selector: 'my-app',
template: `
<div>
<h2>Hello {{name}}</h2>
</div>
`,
styles: [`h2 {
color: red
}`]
})
export class App {
name:string;
constructor() {
this.name = `Angular! v${VERSION.full}`
}
}
Extra attribute will be added to the template elements as follows.
Why component style is not applied to the JQuery plugin?
Inside the plugin the element creation is done by JQuery
instead of Angular. So the attributes used to emulate style scoping is not added to the elements.
To illustrate this, check the below code example in which the dynamic h2
element is appended in the ngAfterViewInit
lifecycle.
@Component({
selector: 'my-app',
template: `
<div>
<h2>Hello {{name}}</h2>
</div>
`,
styles: [`h2 {
color: red
}`]
})
export class App {
name:string; ele;
constructor(eleRef: ElementRef) {
this.name = `Angular! v${VERSION.full}`
this.ele = eleRef;
}
ngAfterViewInit() {
let dynam = document.createElement('h2');
dynam.innerHTML = 'Dynamic content ' + this.name;
this.ele.nativeElement.appendChild(dynam);
}
}
The result will be as follow, you can see that the style from the component is not applied to the dynamically inserted h2 element.
Shadow piercing descendant selector to the rescue
To resolve the above depicted problem, you can use the shadow piercing descendant selector. It is a technique introduced in shadow DOM concept which is deprecated in major browsers.
But you can use this in Angular using the ::ng-deep
special selector. This selector will apply the parent component styles to the descendant child components.
The encapsulation mode should be
Emulated
to use this feature in Angular.
Now the component style should be modified as follows
::ng-deep h2 {
color: red
}
The result will be as follows
Sample
https://plnkr.co/edit/qb9m0qglyDNzmizQkC9d?p=preview