Search code examples
cssangularcss-selectorsshadow-dom

Edit an attribute of the pseudo-class ":host"


In an Angular application, I want to edit the attribute border-top of the pseudo-class :host applied to the component p-table-row, which is a component from a porsche library, so I can't edit it directly.

A picture is worth a thousand word, so here it is : enter image description here

I tried the following CSS selectors but none work.

p-table-row {
  border-top: 1px solid red !important; // cf. image above
}

p-table-body {
  border-top: 1px solid red !important;
}

:host(p-table-body) {
  border-top: 1px solid red !important;
}

:host(p-table-row) {
  border-top: 1px solid red !important;
}

p-table-row :host {
  border-top: 1px solid red !important;
}

I am also willing to use a query selector to edit this attribute, but likewise I don't know how to select the class :host.

Sorry I can't provide a stackblitz, as I can't get it to work with the library I am using.


EDIT: I managed to do it after tweaking the answer from Danny '365CSI' Engelman.

CSS: set border-top as I want it to be.

p-table p-table-row:first-of-type {
  border-top: 1px solid $color-porsche-red-dark;
}

Typescript: set native border-top to null so my css takes precedence (just setting it to the value I want does not work). Note that cssRules[0] refers to :host (I probably should select it by its name but whatever).

ngAfterViewInit(): void {
    setTimeout(() => {
      document
        .querySelectorAll('p-table p-table-row:first-of-type')
        .forEach(el => (el.shadowRoot.adoptedStyleSheets[0].cssRules[0] as CSSStyleRule).style.borderTop = null);
    }, 100);
  }

It works, but the downside is that I need a setTimeout, which I set to a maximum of 100 because above you can see the css being applied, even thought it is just in a blink. Also sometimes the setTimeout is not enough, so I guess there is no perfect solution here.


Solution

  • Experienced developers use !important only when required.
    Remind me not to buy a Porsche.

    You can probably only inject CSS into the existing shadowRoot to overrule earlier STYLE definitions in shadowRoot (but only in open shadowRoots)

    .querySelector("p-table-row")
      .shadowRoot
        .append(
           Object.assign(document.createElement("STYLE"),{
             innerHTML: `:host{1px solid red!important}`
           })
        );
    

    Note: or dig into existing stylesheets, like you added to your question