Custom attribute causes custom element styles to be re-injected into head
- Dominant language
- TypeScript
- Stars
- 11.7k
- Forks
- 608
- PR merge metrics
- No merged PRs in 30d
Description
**I'm submitting a bug report**
From [stack overflow](https://stackoverflow.com/q/45112582/762175) by request of @AshleyGrant.
* **Library Version:**
* bootstrapper: `^2.0.1`
* framework: `1.0.8`
**Please tell us about your environment:**
* **Operating System:**
Windows 10
* **Node Version:**
7.7.3
* **NPM Version:**
4.1.2
* **JSPM**
JSPM 0.17.0-beta.42
* **Browser:**
Chrome 59 (no other supported browser supports Shadow DOM)
* **Language:**
ESNext
**Current behavior:**
Shadow DOM scoped CSS includes are injected into the shadow root _and into ``_.
**Expected/desired behavior:**
Shadow DOM scoped CSS includes are injected _only_ into the shadow root.
---
**From Stack Overflow:**
In my aurelia application, one of my custom elements `panel` (shadow DOM) includes another custom element `widget` (shadow DOM) that has a custom attribute `own-attribute` (template controller) on it. `panel` has a scoped stylesheet (``). While compiling, aurelia correctly injects `./panel.css` into the shadow root of `panel`. However, in a separate step, while compiling `own-context` on `widget` within `panel`, aurelia injects `./panel.css` into ``, thus breaking the abstraction of custom element stylesheets and generally playing havoc with my app.
How do I fix this?
I tried making a plunker [here](https://embed.plnkr.co/L065Tu/) but it doesn't work. I'm using ES2017 so that makes life more complicated.
---
- `panel` is being compiled by [`ViewCompiler.compile()`](https://github.com/aurelia/templating/blob/f13620127cc5d22d2943a9b3778c91ef96e248ba/src/view-compiler.js#L77)
- This [calls `ViewCompiler._compileNode()`](https://github.com/aurelia/templating/blob/f13620127cc5d22d2943a9b3778c91ef96e248ba/src/view-compiler.js#L98)
- This [calls itself](https://github.com/aurelia/templating/blob/f13620127cc5d22d2943a9b3778c91ef96e248ba/src/view-compiler.js#L153) on `widget`
- This [calls `ViewCompiler._compileElement()`](https://github.com/aurelia/templating/blob/f13620127cc5d22d2943a9b3778c91ef96e248ba/src/view-compiler.js#L129) on `widget`
- This detects `own-context` as a "lifting instruction" and [calls `HtmlBehaviorResource.compile()`](https://github.com/aurelia/templating/blob/f13620127cc5d22d2943a9b3778c91ef96e248ba/src/view-compiler.js#L417)
- This [calls `ViewCompiler.compile()`](https://github.com/aurelia/templating/blob/f13620127cc5d22d2943a9b3778c91ef96e248ba/src/html-behavior.js#L238) on `widget`
- As a [`beforeCompile` `invokeHook`](https://github.com/aurelia/templating/blob/f13620127cc5d22d2943a9b3778c91ef96e248ba/src/view-compiler.js#L95), [`CSSViewEngineHooks.beforeCompile()`](https://github.com/aurelia/templating-resources/blob/master/src/css-resource.js#L64), is called, which injects a bunch of styles into ``
This is an issue. `HtmlBehaviorResource.compile()`'s call to `ViewResource.compile()` does not pass a compile instruction, so the latter uses the default. Thus the CSS hooks don't get the message that they should be injecting into the shadow root. Not to mention this is double-injecting these styles for no good reason.
at eval (eval at injectStyles (http://example.com/jspm/npm/aurelia-pal-browser@1.1.0/aurelia-pal-browser.js), :1:11)
at Object.injectStyles (http://example.com/jspm/npm/aurelia-pal-browser@1.1.0/aurelia-pal-browser.js:434:27)
at ViewCSS.beforeCompile (http://example.com/jspm/npm/aurelia-templating-resources@1.2.0/css-resource.js:105:25)
at ViewResources._invokeHook (http://example.com/jspm/npm/aurelia-templating@1.2.0/aurelia-templating.js:1281:25)
at ViewCompiler.compile (http://example.com/jspm/npm/aurelia-templating@1.2.0/aurelia-templating.js:2509:17)
at HtmlBehaviorResource.compile (http://example.com/jspm/npm/aurelia-templating@1.2.0/aurelia-templating.js:3972:46)
at ViewCompiler._compileElement (http://example.com/jspm/npm/aurelia-templating@1.2.0/aurelia-templating.js:2813:40)
at ViewCompiler._compileNode (http://example.com/jspm/npm/aurelia-templating@1.2.0/aurelia-templating.js:2543:23)
at ViewCompiler._compileNode (http://example.com/jspm/npm/aurelia-templating@1.2.0/aurelia-templating.js:2565:33)
at ViewCompiler.compile (http://example.com/jspm/npm/aurelia-templating@1.2.0/aurelia-templating.js:2512:12)
---
### panel.js
```javascript
import { useShadowDOM, customElement } from 'aurelia-templating';
export { PanelModule };
@useShadowDOM
@customElement('panel-elem')
class PanelModule {}
```
### panel.html
```html
some content
```
### widget.js
```javascript
import { useShadowDOM, customElement } from 'aurelia-templating';
export { WidgetModule };
@useShadowDOM
@customElement('widget-elem')
class WidgetModule {}
```
### widget.html
```html
```
### own-context.js
```javascript
import { inject, templateController, BoundViewFactory, ViewSlot } from 'aurelia-framework';
import { createOverrideContext } from 'aurelia-binding';
// from https://github.com/aurelia/templating/issues/411
@templateController
@inject(BoundViewFactory, ViewSlot)
class OwnContextCustomAttribute {
constructor(factory, slot) {
this.factory = factory;
this.slot = slot;
}
bind(bindingContext, overrideContext) {
let newContext = { };
overrideContext = createOverrideContext(newContext, overrideContext);
if (!this.view) {
this.view = this.factory.create();
this.view.bind(newContext, overrideContext);
this.slot.add(this.view);
} else {
this.view.bind(newContext, overrideContext);
}
}
unbind() {
if (this.view)
this.view.unbind();
}
}
```
Contributor guide
Research direction
Start with ViewCompiler.compile(), ViewCompiler._compileNode(), ViewCompiler._compileElement(), and HtmlBehaviorResource.compile(), following the linked call chain into CSSViewEngineHooks.beforeCompile() in css-resource.js. Reproduce the panel/widget/own-context example and verify that scoped CSS is injected only into the shadow root, not duplicated in .
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- frontend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 35/100