1
votes

with Polymer it's easy to extend another web component. You can use <shadow> to mark the place in the child's template where the shadow dom of the Parent should be (polymer docs).

I'm looking to extend an element, but in a way that a specific part of child gets wrapped by the parent. This kind of setup I've used with some template engines. Can this be done with html includes?

Parent ::

<link rel="import" href="/bower_components/polymer/polymer.html">

<polymer-element name="tpl-parent" noscript>
  <template>
    <section>
      <content></content><!-- put the child template here -->
    </section>
  </template>
</polymer-element>

Child ::

<link rel="import" href="/bower_components/polymer/polymer.html">
<link rel="import" href="parent.html">

<polymer-element name="tpl-child" extends="tpl-parent" noscript>
  <template>
    <shadow>
      <p>whatever I put here should be "wrapped" by the _section_ in parent</p>
    </shadow>
  </template>
</polymer-element>
2

2 Answers

3
votes

You can't do it declaratively like that. But I think you can leverage automatic node finding to move a child into the parent's section if it has an id.

<polymer-element name="x-foo">
  <template>
    <style>
      #wrapper p { color: red; }
    </style>
    <section id="wrapper">
      <p>Hello from x-foo</p>
    </section>
  </template>
  <script>
    Polymer({

    });
  </script>
</polymer-element>

<polymer-element name="x-bar" extends="x-foo">
  <template>
    <p id="foo">I was wrapped by x-foo</p>
    <p>I was not wrapped</p>
    <shadow></shadow>
  </template>
  <script>
    Polymer({
      domReady: function() {
        this.$.wrapper.appendChild(this.$.foo);
      }
    });
  </script>
</polymer-element>

<x-bar></x-bar>
1
votes

Even though @robdodson's answer is completely correct, it kind of feels.. too "loose".

When discussing this further at work, somebody noted the principle of "Composition over inheritance". This led to me viewing this situation from a different (and I think better) perspective.

I ended up with this (also includes an example of passing arguments):

-- x-foo.html

<polymer-element name="x-foo" arguments="status">
  <template>
    <style>
      #wrapper.valid ::content p { color: green; }
      #wrapper.invalid ::content p { color: red; }
    </style>
    <section id="wrapper">
      <p>x-bar will be put in the content tag below</p>
      <content></content>
    </section>
  </template>
  <script>
    Polymer({
      status: '',
      statusChanged: function(oldVal, newVal) {
        if (['valid', 'invalid'].indexOf(newVAl) === -1) {
          this.$.wrapper.setAttribute('class', newVal);
        }
      }
    });
  </script>
</polymer-element>

-- x-bar.html

<link rel="import" href="x-foo.html" arguments="status">

<polymer-element name="x-bar">
  <template>
    <x-foo status="{{status}}">
      <p>color me</p>
    </x-foo>
  </template>
  <script>
    Polymer();
  </script>
</polymer-element>

-- index.html

<link rel="import" href="x-bar.html" arguments="status">
<x-bar></x-bar>

The only "disadvantage" is you have to pass on "status". But this feels better then having to append to a "floating" div#wrapper in the super class