3

I do have several nested polymer elements created by myself. Currently with using polymers shared styles I'm able to inject custom styling into other elements. Unfortunately this approach is restricted to static use. So at implementation time I do need to know which Element should use which shared style by import the shared style module with <link rel="import" href="my-shared-style.html"> and <style include="my-shared-style"></style>.

But in my use case I do need to inject shared styles into polymer elements at runtime. Is there any possibility to achieve this?

UPDATE

I tried following approach inspired by Günters answer below:

Polymer({
    is : 'html-grid-row',
    /**
    * Inject style into element
    * @param {string} style
    */
    injectStyle : function(style) {
        var customStyle = document.createElement('style', 'custom-style');
        customStyle.textContent = style;
        Polymer.dom(this.root).appendChild(customStyle);
    }
    /**
    * Additional Elements JS functionality is put here...
    *
    */
)}

When I now try to dynamically add style by calling injectStyle('div {font-weight: bold;}') on elements instance at runtime the style module is injected into the element but is not displayed because polymer seems to edit custom-styles text content like the following:

<style is="custom-style" class="style-scope html-grid-row">
    div:not([style-scope]):not(.style-scope) {font-weight: bold;}
</style>

Is there a way to prevent polymer from adding the :not([style-scope]):not(.style-scope) prefix to style rules?

UPDATE 2:

Referencing a global shared style using include='my-shared-style' does have the same effect.

Include this shared style which is statically imported globally using html import:

<dom-module id="my-shared-style">
    <template>
        <style>
            div {
                font-weight: bold;
            }
        </style>
    </template>
</dom-module>

After dynamically import and referencing shared-style Polymer includes following:

<style is="custom-style" include="my-shared-style" class="style-scope 
 html-grid-row">
    div:not([style-scope]):not(.style-scope) {
        font-weight: bold;
    }
</style> 

SOLUTION

Finally I used a workaround for dynamically inject styling into Polymer elements at runtime by extending the <style> HTML Element with document.register('scoped-style', {extends : 'style', prototype : ...}). The injectStyle(style) method (see above) now creates a <style is="scoped-style"> element directly as child of the Elements root node. Indeed it's inspired by https://github.com/thomaspark/scoper. This works so far for me.

phwa4563
  • 456
  • 6
  • 17
  • 2
    I guess you can't just set the `textContent` use the `include` attribute of `custom-style`. I don't use JS myself (only Dart) therefore it's hard for me to create proper JS translation. – Günter Zöchbauer Feb 03 '16 at 08:10
  • I didn't dive into how the CSS-shims work. What problem does this rewrite cause? – Günter Zöchbauer Feb 03 '16 at 09:02
  • For each DOM node inside the template tag of the Polymer Element a css class `style-scope [element name]` ist added. So the `:not([style-scope])` and `:not(.style-scope)` pseudo classes that are added by polymer in my dynamically added CSS Styles causes these styles to not apply to the HTML this Poylmer Element contains inside the template tag. – phwa4563 Feb 03 '16 at 12:27
  • Sounds weird. I didn't have such issues. This is not about elements projected using the `` tag? You could try to use `:host div {` as selector. – Günter Zöchbauer Feb 03 '16 at 12:30
  • Don't know why polymer is having such behaviour. But for now I do have a workaround that fits me needs (see SOLUTION above). Nevertheless I will support your feature request regarding dynamic styling on Polymers GitHub project :-) – phwa4563 Feb 03 '16 at 14:34

1 Answers1

5

I used something like this successfully to inject styles dynamically

var myDomModule = document.createElement('style', 'custom-style');
myDomModule.setAttribute('include', 'mySharedStyleModuleName');
Polymer.dom(sliderElem.root).appendChild(myDomModule);

The style-module 'mySharedStyleModuleName' needs to be imported somewhere (like index.html).

See also https://github.com/Polymer/polymer/issues/2681 about issues I run into with this approach and https://stackoverflow.com/a/34650194/217408 for more details

Community
  • 1
  • 1
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567