ionelmc
ionelmc

Reputation: 721

Best way to deal with polymer element inheritance

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:

Upvotes: 21

Views: 2034

Answers (1)

Scott Miles
Scott Miles

Reputation: 11027

  • What's the best way to specify additional styling ?
  1. Put a template inside the subclass (my-custom-element), as usual.
  2. Include a <shadow></shadow> element where you want the superclass template to appear.
  3. Put a style tag into the new template.
  4. 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.

Upvotes: 12

Related Questions