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.