Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to extend PolymerElements? #4686

Closed
iSuslov opened this issue Jun 14, 2017 · 5 comments
Closed

How to extend PolymerElements? #4686

iSuslov opened this issue Jun 14, 2017 · 5 comments

Comments

@iSuslov
Copy link

iSuslov commented Jun 14, 2017

I'm trying to extend app-drawer following the instructions here #4556
Having this code I'm getting the following error in chrome. Other browsers not tested.

customElements.whenDefined('app-drawer').then(() => {
            class MobileLeftMenu extends customElements.get("app-drawer") {
                static get is() {
                    return 'mobile-left-menu'
                }
            }
            customElements.define(MobileLeftMenu.is, MobileLeftMenu);
})

error:

app-drawer.html:514 Uncaught TypeError: Cannot read property 'style' of undefined
    at HTMLElement._styleTransitionDuration (app-drawer.html:514)
    at Object.runMethodEffect [as fn] (property-effects.html:771)
    at runEffectsForProperty (property-effects.html:137)
    at runEffects (property-effects.html:103)
    at HTMLElement._propertiesChanged (property-effects.html:1564)
    at HTMLElement._flushProperties (property-accessors.html:512)
    at HTMLElement.ready (property-effects.html:1522)
    at HTMLElement.ready (element-mixin.html:654)
    at HTMLElement.ready (legacy-element-mixin.html:151)
    at HTMLElement.ready (class.html:205)

Is it possible to extend PolymerElements at all? No documentation found

@arthurevans
Copy link

You can. There are some docs here:

https://www.polymer-project.org/2.0/docs/devguide/custom-elements#extending-other-elements
https://www.polymer-project.org/2.0/docs/devguide/dom-template#inherited-templates

I can't reproduce your error with the code you showed above, but if I add a new <dom-module> with a template for this element, I get the error.

So it looks like you're replacing the template of the parent element. If you want to insert content into the parent element template, see the second link above. You can also use composition (create a parent element that includes an app-drawer with some contents).

One catch with extending an element and manipulating its template is that you need to know which internal elements the parent element references (for example, in this case, the app-drawer code is trying to access this.$.contentContainer, but that element doesn't exist in the new template).

@dfreedm
Copy link
Member

dfreedm commented Jun 17, 2017

Extending other elements and modifying templates is a topic that probably needs a bit more exploration and documentation for good patterns.

@kevinpschaaf
Copy link
Member

kevinpschaaf commented Jun 19, 2017

Two safe patterns you can use when subclassing and modifying a template are:

  1. clone the super class template and wrap it with additional DOM (e.g. insert the parent template into a new template)
  2. clone the super class template and insert additional DOM into it

Creating a new template for the subclass from whole cloth is more risky because as @arthurevans pointed out Polymer elements may reference specific nodes from the template in imperative code (typically nodes with id via the this.$ map), so you need to maintain that id-node contract in the sub template, or else override the methods with those references. This is less of an issue when elements only modify their templates via data-binding, since the links to the template via the data-binding are re-evaluated with each new template.

@clint77
Copy link

clint77 commented Nov 14, 2017

Here is an example of how to extend element and also cloning the template and being able to use own <style> on the sub-element. Also a link to @kevinpschaaf kevinpschaaf example from another thread is here

Below is gist of how template can be cloned plus attached the <style>

  let subTemplate;

  static get template() {
     if (!subTemplate) {
       // first clone our superclass <app-drawer> template
       let superClass = customElements.get('app-drawer');
       subTemplate = superClass.template.cloneNode(true);

        // here we will get the content of our <style> so we can insert them into the superclass <style>
        // note the added id="styles" in our template tag above
          const subStyle = Polymer.DomModule.import('my-sub-element', 'template#styles').content;

        // get the content of current style from superClass
        const superStyle = subTemplate.content.querySelector('style');

        // append our added style at the bottom of the current style to get higher priority
        superStyle.parentNode.appendChild(subStyle);
      }
      return subTemplate;
  }

@sorvell
Copy link
Contributor

sorvell commented Dec 11, 2017

Closing since there are now a number of examples about how to do this. Please re-open if it needs further clarification.

@sorvell sorvell closed this as completed Dec 11, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants