7

I know there is this question on multiple inheritance/composition. However, it seems like this question is more about how to reuse functionality from multiple existing elements in other elements. And obviously, the solution for that are mixins.

I would like to know, how I can actually "decorate" existing elements without really borrow functionality from them. We know there is this extends property one can use to extend an existing element with Polymer.

So making a normal <button> behave like a mega-button is as simple as attaching <button is="mega-button"> and write a component for it. But it turns out, that it's not possible to extend multiple elements. So something like extends="foo bar" doesn't work. What if I want to build a web component, that can actually be applied to different elements?

For example, I don't want to only extend <button> elements with mega-button but probably also an <a> element so that it looks like and behaves like a mega-button too?

The mixin approach doesn't really help here (as far as I get it), because they do nothing more then providing shared logic for different web components. That means, you create multiple components, and reuse logic (packed in a mixin) from a mixin.

What I need is a way to create one web component that can be applied to multiple elements.

Any idea how to solve that?

UPDATE

Addy answered with some approaches to handle that use case. Here's a follow up question based on one approach

How to find out what element is going to be extended, while registering my own in Polymer

And another one on Is it possible to share mixins across web components (and imports) in Polymer?

UPDATE 2

I've written an article and concludes my experiences and learnings about inheritance and composition with polymer: http://pascalprecht.github.io/2014/07/14/inheritance-and-composition-with-polymer/

Community
  • 1
  • 1
Pascal Precht
  • 8,803
  • 7
  • 41
  • 53
  • I found another approach right here: https://github.com/mvaldetaro/twbs-buttons. The author of this project provides and API by publishing a `tag` attribute that let you specify the actual html tag that should be used. In the web components implementation, you can see that he checks for different tag names and uses different template contents accordingly. Definitely *not* the way to go in my opinion. – Pascal Precht Jun 11 '14 at 08:25

1 Answers1

2

If you need to have just a single import that has support for being applied to multiple elements, your element could include multiple element definitions which may or may not take advantage of Polymer.mixin in order to share functionality between your decorating elements.

So pascal-decorator.html could contain Polymer element definitions for <pascal-span> and <pascal-button>, both of which mixin logic from some object defined within pascal-decorator.html. You can then do <button is="pascal-button"> and <button is="pascal-span"> whilst the logic for doing so remains inside the same import.

The alternative (if you strictly want to do this all in one custom element, which imo, makes this less clean) is to do something like checking against the type of element being extended, which could either be done in the manner you linked to or by checking as part of your element registration process.

In general, I personally prefer to figure out what logic I may need to share between elements that could be decorated, isolate that functionality into an element and then just import them into dedicated elements that have knowledge about the tag (e.g <addy-button>, <addy-video> etc).

addyo
  • 2,798
  • 1
  • 14
  • 21
  • Addy, thanks for your detailed answer. While I understand the different ways to handle that scenario, I'm still not sure if that is what one want in certain cases. I think the twbs-buttons are a perfect example. You could have anchor tags, or button elements in your application that look (and probably behave) like a twitter button. So what you want to have then is being able to do sth. like ` – Pascal Precht Jun 11 '14 at 12:41
  • The best practices around this are still evolving :) It would be helpful to know if there's a concrete example of what you're trying to achieve (what functionality are you trying to decorate these elements with?). If it's a case of wanting to extend behaviour (e.g interaction/clicks/touch) using the same element to support the general extension use-case should work without much need to check on type. Visuals are where further care needs to be taken and that's where I'd consider specific elements being needed. – addyo Jun 11 '14 at 12:51
  • Well, actually I have the exact same scenario I described here. I'm trying to build web components for the Ionic framework. And there's a button component (of course, it's just a css class), that has theming support etc. So actually currently it's all about css where no custom element is needed at all, but there might be situations where I need JS logic when the component is used with a ` – Pascal Precht Jun 11 '14 at 13:04
  • So my idea for now was to just use `is=""` and make my component `theme-aware` so that I'm able to apply my element extension on common elements like `` etc. – Pascal Precht Jun 11 '14 at 13:06
  • That approach seems legit. – addyo Jun 11 '14 at 13:45
  • Yes, but unfortunately not possible unless I create multiple elements. So it looks like I have to create elements for the most common use cases (`` and ` – Pascal Precht Jun 11 '14 at 13:50
  • I'd this is for theming, check out core-style. Each element that needs to be themed include. It's replacing theme-aware – ebidel Jun 11 '14 at 15:18
  • Thank you Eric! I'll take a look at it and update this question! – Pascal Precht Jun 11 '14 at 15:57
  • I added a follow up question: http://stackoverflow.com/questions/24179075/how-to-find-out-what-element-is-going-to-be-extended-while-registering-my-own-i – Pascal Precht Jun 12 '14 at 07:56