This Banner is For Sale !!
Get your ad here for a week in 20$ only and get upto 15k traffic Daily!!!

How ViewEncapsulation and ng-deep work in Angular


Keep default Angular ViewEncapsulation
Many Angular builders and format designers who write CSS/SCSS code in Angular functions have encountered a scenario the place they should apply kinds to a part nested within the present one and, with out absolutely understanding the way it works, turned off model encapsulation or added ng-deep, whereas not making an allowance for some nuances, which later results in issues. On this article, I’ll attempt to current all the main points as merely and concisely as doable.
When a part has model encapsulation enabled (it’s enabled by default and needs to be left enabled generally), the kinds contained within the part’s model filefiles will solely apply to the parts’ components. That is very handy, you do not have to maintain observe of the distinctiveness of the selectors, you do not have to make use of BEM or provide you with lengthy class names and preserve them distinctive, though you’ll be able to nonetheless do this if you would like. Throughout the creation of every part, Angular itself will add a singular attribute to all components contained in the part, for instance, _ngcontent-ool-c142 and exchange your .my-class selector with .my-class[_ngcontent-ool-c142] (that is within the case of ViewEncapsulation.Emulated , which is enabled by default, if you happen to specify ViewEncapsulation.ShadowDom the conduct is completely different however the outcome is identical).

Now we could say that now we have a part named ComponentA

<div class="checkbox-container">
  <mat-checkbox>Test me</mat-checkbox>
</div>
Enter fullscreen mode

Exit fullscreen mode

that has a mat-checkbox from Angular materials nested inside it (this may be your personal part, not essentially parts from libraries).

Inside mat-checkbox there’s a label that we wish to add a border to.

<mat-checkbox>
  <label>
...
Enter fullscreen mode

Exit fullscreen mode

If we write within the part’s model file,

mat-checkbox label {
  border: 1px strong #aabbcc;
}
Enter fullscreen mode

Exit fullscreen mode

then after making use of ViewEncapsulation.Emulated the selector will probably be one thing like this

mat-checkbox[_ngcontent-uiq-c101]   label[_ngcontent-uiq-c101] {
  border: 1px strong #aabbcc;
}
Enter fullscreen mode

Exit fullscreen mode

i.e. the border will probably be utilized to the label with the _ngcontent-uiq-c101 attribute, however all youngster components contained in the mat-checkbox could have a unique attribute because the label is inside one other part and it’ll both have an attribute with a unique ID (id of mat-checkbox part), or it won’t exist in any respect if the part, in flip, has encapsulation disabled (in our case, there will probably be no attribute in any respect, as a result of mat-checkbox, like different parts from Angular Materials has ViewEncapsulation.None).
Thus, kinds restricted by the ComponentA part attribute solely apply to components instantly inside that part. If the part incorporates one other part, then these kinds now not apply to its components.
For those who’re questioning precisely how Angular’s Emulated encapsulation works, you will discover numerous detailed articles on the topic, however right here I am going to give a really transient description in order to not bloat the article. If the part has encapsulation, then the _nghost-ID attribute will probably be added to the part itself, and the _ngcontent-ID attribute will probably be added to every nested component, and [_ngcontent-ID] will probably be added to all kinds on this part. This manner all kinds will probably be utilized ONLY to the weather inside that part.

What if we have to apply kinds to the weather contained in the nested part (in our instance, to the label contained in the mat-checkbox)

With a view to apply kinds, now we have three choices:

  • disable model encapsulation in ComponentA
  • use ng-deep
  • place css code in world kinds (these in kinds.(s)css or in different information specified within the kinds part in angular.json)

Let’s take a better take a look at them



ViewEncapsulation.None

On this case, all kinds contained in the part will turn out to be “world”, and this may occur solely after the part is created, i.e. after the person has visited the part of the appliance the place this part is used, which makes it very troublesome to establish this drawback. Let’s flip off model encapsulation on our part.

@Element({
  selector: 'app-component-a',
  templateUrl: './component-a.part.html',
  styleUrls: ['./component-a.component.scss'],
  encapsulation: ViewEncapsulation.None
})
Enter fullscreen mode

Exit fullscreen mode

do not forget that within the model file now we have this

mat-checkbox label {
  border: 1px strong #aabbcc;
}
Enter fullscreen mode

Exit fullscreen mode

till the person has opened the web page the place part A is used, all different mat-checkboxes within the software look borderless, however after part A has rendered, the css code above will probably be dynamically added to the part within the DOM tree and after then all mat-checkboxes will use these kinds.
With a view to stop this apparently undesirable impact, we are able to restrict the scope of kinds by making use of a extra particular selector. For instance, let’s add the “checkbox-container” class to the mat-checkbox’s mum or dad component,

<div class="checkbox-container">
  <mat-checkbox>Test me</mat-checkbox>
</div>

and repair the selector to this

.checkbox-container mat-checkbox label {
  border: 1px strong #aabbcc;
}

now solely checkboxes positioned inside a component with the checkbox-container class will get the border. However as a substitute of including a category with a singular identify and ensuring they are not repeatable, it is a lot simpler to make use of a part selector, as a result of it will likely be distinctive

app-component-a mat-checkbox label {
  border: 1px strong #aabbcc;
}

Conclusion: if you happen to flip off encapsulation, do not forget so as to add the part selector to ALL kinds contained in the part, in case of SCSSSASS, simply wrap all code in:



Pseudo-class ng-deep

Now let’s flip encapsulation again on by eradicating encapsulation: ViewEncapsulation.None from the @Element decorator. And add the ::ng-deep selector to the css

::ng-deep mat-checkbox label {
  border: 1px strong #aabbcc;
}

ng-deep will pressure the framework to generate kinds with out including attributes to them, consequently, this code will probably be added to the DOM:

mat-checkbox label{border:1px strong #aabbcc}

which is able to have an effect on all mat-checkbox functions, identical to if we added it to world kinds or turned off encapsulation as we did earlier. To keep away from this conduct, we are able to once more limit the scope to the part selector

::ng-deep app-component-a mat-checkbox label {
  border: 1px strong #aabbcc;
}

or do it even easier and use the :host pseudo-class

:host ::ng-deep mat-checkbox label {
  border: 1px strong #aabbcc;
}

which is way more handy and dependable (think about if you happen to renamed the part selector and forgot to alter it within the css code).
How does it work? Quite simple – Angular will generate on this case the next kinds

[_nghost-qud-c101] mat-checkbox label{border:1px strong #aabbcc}

the place _nghost-qud-c101 is the attribute added to our ComponentA, i.e. the border will apply to all labels inside any mat-checkbox mendacity inside a component with the _nghost-qud-c101 attribute, which ONLY ComponentA has.

<app-component-a _ngcontent-qud-c102 _nghost-qud-c101>

Conclusion: if utilizing ::ng-deep ALWAYS add :host or create a mixin and use it all over the place

@mixin ng-deep {
  :host ::ng-deep {
    @content material;
  }
}

@embrace ng-deep {
  mat-checkbox label {
    border: 1px strong #aabbcc;
  }
}

Many builders are confused by the truth that ng-deep has been marked as deprecated for a very long time. The Angular staff had plans to deprecate this pseudo-class, however that call was later shelved indefinitely, no less than till new options come alongside. If we evaluate ng-deep and ViewEncapsulation.None, then within the first case, we no less than flip off encapsulation not for all part kinds, however just for people who we’d like. Even if in case you have a part the place all of the kinds are for youngster parts, ng-deep appears to be extra advantageous as a result of you’ll be able to later add kinds for the part’s personal components, during which case you simply write them above/beneath the code nested in :host ::ng-deep {} and they’re going to work as common, however with encapsulation disabled, you now not have this feature.

Lastly, I wish to add just a few phrases about the right way to “model” parts from libraries. If you might want to change the default view for, say, all mat-selects in your software, it is typically greatest to take action in world kinds. Typically, some builders choose to place these kinds in a separate SCSS file and import it wherever wanted, however on this case, when constructing the challenge, these kinds are duplicated in every chank (compiled js file for a lazy or shared module / group of modules) , the place no less than one of many parts included on this chank makes use of this model file, which might considerably enhance the whole measurement of the bundle. Subsequently, this observe needs to be prevented.

The Article was Inspired from tech community site.
Contact us if this is inspired from your article and we will give you credit for it for serving the community.

This Banner is For Sale !!
Get your ad here for a week in 20$ only and get upto 10k Tech related traffic daily !!!

Leave a Reply

Your email address will not be published. Required fields are marked *

Want to Contribute to us or want to have 15k+ Audience read your Article ? Or Just want to make a strong Backlink?