Best way to deal with polymer element inheritance

css, html, javascript, polymer, web-component

Solution

- What's the best way to specify additional styling ?

- Put a template inside the subclass (`my-custom-element`), as usual.

- Include a `<shadow></shadow>` element where you want the superclass template to appear.

- Put a style tag into the new template.

- To style elements that come from the superclass template, use a selector like this:

`:host::shadow .someclass { ... }`

See example below.

- Can I wrap the base element in additional markup (like another container) ?

Yes, you can put whatever markup you want around the `<shadow></shadow>`.

<div>
  <shadow></shadow>
</div>

- Can I select elements from the base element? Something like `<content select=".stuff">` but for the base's shadow markup.

No. You cannot project like that (it's the reverse direction from all other projections).

If you really want to cherry-pick nodes out of the older shadow-root, this can be done in code by pulling nodes directly out of `this.shadowRoot.olderShadowRoot`. But this can be tricky because the superclass may have expectations about the structure.

Example code:

<polymer-element name="my-custom-element" extends="custom-element">
<template>

  <style>
      /* note that :host::shadow rules apply 
         to all shadow-roots in this element,
         including this one */
      :host::shadow #container { 
        color: blue;
      }
      :host {
        /* older shadow-roots can inherit inheritable 
           styles like font-family */
        font-family: sans-serif;
      }
  </style>
  <p>
    <shadow></shadow>
  </p>

</template>
<script>

  Polymer('my-custom-element', {
    clickContainer: function() {
      this.super();
    }
  });

</script>
</polymer-element>

ProTips:

- `olderShadowRoot` will exist whether or not you include the `<shadow></shadow>` tag, but it will not be part of the rendered DOM unless you do.

- to prevent `olderShadowRoot(s)` from being created you can override `parseDeclarations` (source). Any of `parseDeclarations`, `parseDeclaration`, `fetchTemplate` can be overidden for various effects.

Problem

Given an element like: ``` <polymer-element name="custom-element"> <template> <style> #container { color: red; } </style> <div id="container" on-click="{{clickContainer}}"> ... lots of other stuff here ... </div> </template> <script> Polymer('custom-element', { clickContainer: function() { } }); </script> </polymer-element> ``` I'd like to have another element that wraps the first: ``` <polymer-element name="my-custom-element" extends="custom-element"> <!-- extra styling --> <script> Polymer('my-custom-element', { clickContainer: function() { this.super(); } }); </script> </polymer-element> ``` My problems: - What's the best way to specify additional styling ? - Can I wrap the base element in additional markup (like another container) ? - Can I select elements from the base element ? Something like `<content select=".stuff">` but for the base's shadow markup.

Original source