2.0.3 • Published 4 years ago

angular-pass-on-encap v2.0.3

Weekly downloads
3
License
ISC
Repository
github
Last release
4 years ago

passOnEncapsulationDirective

Directive for Angular to pass on a parents encapsulation attribute to its children.

How to use

Install package in your angular project

npm install -s angular-pass-on-encap

Import module into your app.module.ts

import { PassOnEncapsulationModule } from 'angular-pass-on-encap';

@NgModule({
  imports: [
    PassOnEncapsulationModule
  ]
})

Use the directive:

<mat-form-field libPassOnEncap></mat-form-field>

Explanation

When ViewEncapsulation.Emulated is enabled in Angular (default), it adds an attribute to your HTML elements and CSS classes to keep your css rules inside the component. This is great if you only use your own components, since you can edit their respective styles directly. However, when you use other packages, f.e. Angular Material, you don't have access to the component's children.

Example: How it works now

In this example, I'm using a mat-form-field component in my-component:

<!--my-component.html-->
<mat-form-field>
  <input matInput placeholder="placeholder" />
</mat-form-field>

Then I want to apply a new border to the field label wrapper, created inside mat-form-field:

/* my-component.css */
.mat-form-field-label-wrapper {
    border: 1px solid red;
}

However, when the resulting html and CSS is sent to the browser, my rule is ignored:

<mat-form-field class="mat-form-field" _ngcontent-rwb-c0>
  <div class="mat-form-field-wrapper">
    <div class="mat-form-field-flex">
      <div class="mat-form-field-infix">
        <input class="mat-input-element"_ngcontent-rwb-c0/>
        <!-- I want to edit this: -->
        <span class="mat-form-field-label-wrapper">
          <label class="mat-form-field-label">
            <span>placeholder</span>
          </label>
        </span>
      </div>
    </div>
    <div class="mat-form-field-underline">
      <span class="mat-form-field-ripple"></span>
    </div>
    <div class="mat-form-field-subscript-wrapper">
      <div class="mat-form-field-hint-wrapper">
        <div class="mat-form-field-hint-spacer"></div>
      </div>
    </div>
  </div>
</mat-form-field>
.mat-form-field-label-wrapper[_ngcontent-rwb-c0] {
    border: 1px solid red;
}

Angular uses randomly generated attributes, in this case _ngcontent-rwb-c0, to bind the CSS rules to the components HTML elements. But Angular only adds the attribute to the 'root' elements which are positioned directly in my template. In this case my css rule for .mat-form-field-label-wrapper will not be applied to the element. I will need to put it in the global style.css where no encapsulation tag is added to the CSS class. But this becomes tedious quickly, expecially when I want to display .mat-form-field-label-wrapper differently in several components; and it defeats the whole purpose of encapsulation.

Example: How it works with directive

Using libPassOnEncap in the components lets it pass on its encapsulation attribute to its children:

<!--my-component.html-->
<mat-form-field libPassOnEncap>
  <input matInput placeholder="placeholder"/>
</mat-form-field>
<mat-form-field class="mat-form-field" _ngcontent-rwb-c0>
  <div class="mat-form-field-wrapper" _ngcontent-rwb-c0>
    <div class="mat-form-field-flex" _ngcontent-rwb-c0>
      <div class="mat-form-field-infix" _ngcontent-rwb-c0>
        <input class="mat-input-element" _ngcontent-rwb-c0/>
        <span class="mat-form-field-label-wrapper" _ngcontent-rwb-c0>
          <label class="mat-form-field-label" _ngcontent-rwb-c0>
            <span _ngcontent-rwb-c0>placeholder</span>
          </label>
        </span>
      </div>
    </div>
    <div class="mat-form-field-underline" _ngcontent-rwb-c0>
      <span class="mat-form-field-ripple" _ngcontent-rwb-c0></span>
    </div>
    <div class="mat-form-field-subscript-wrapper" _ngcontent-rwb-c0>
      <div class="mat-form-field-hint-wrapper" _ngcontent-rwb-c0>
        <div class="mat-form-field-hint-spacer" _ngcontent-rwb-c0></div>
      </div>
    </div>
  </div>
</mat-form-field>

Now my CSS rule for .mat-form-field-label-wrapper works and it works only for elements inside this component.

2.0.3

4 years ago

2.0.2

4 years ago

2.0.1

4 years ago

2.0.0

4 years ago

1.0.0

4 years ago