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

test-button element class with extends="button" can't be instantiated with <test-button> syntax #334

Closed
JanMiksovsky opened this issue Nov 1, 2013 · 8 comments

Comments

@JanMiksovsky
Copy link

See http://jsbin.com/aMufARI/1/edit.

The <button is="test-button"> instance works as expected, but the <test-button> instance does not. When I look at it right now, the latter doesn't even get a shadow root.

@morethanreal
Copy link
Contributor

If your custom element extends from an existing DOM element, you need to
use the syntax to instantiate one.

On Fri, Nov 1, 2013 at 11:41 AM, Jan Miksovsky [email protected]:

See http://jsbin.com/aMufARI/1/edit.

The instance works as expected, but the instance does not. When I look at
it right now, the latter doesn't even get a shadow root.


Reply to this email directly or view it on GitHubhttps://github.com//issues/334
.

@JanMiksovsky
Copy link
Author

Is that a permanent restriction, or is this still up for debate?

I ask because this point would be a significant limitation for a number of elements I'm working on. I'm porting some elements from an earlier web component framework to Polymer. A number of those components create sub-components, and let the host specify the class for those sub-components.

Take the example of a month calendar element of the type seen at http://quickui.org/catalog/CalendarMonth. (This uses an older component framework called QuickUI.) This component attempts to deliver a very general-purpose month calendar that can be extended in ways that go far beyond what's possible in CSS. Towards that end, the component allows a host to specify the element class that should be used to render the individual days in the month calendar.

By default, the month calendar uses a simple baseline element class that just renders a date, but the month calendar component allows this baseline class to be swapped out for a different element class that can supply its own subtree. For example, this same month calendar is used as the basis for a CalendarMonthNavigator component in which the day elements are rendered with an element class whose representation includes a button, in order to make dates fully clickable. A more elaborate calligraphy calendar demo supplies a day element class that renders a day with both Arabic numerals and kanji calligraphy. For that degree of customizability, CSS is insufficient — one needs the ability to specific both DOM content and behavior. And the best way to supply content and behavior is with a custom element. That is, one wants to be able to set an attribute on the month calendar that indicates which element class should be instantiated to represent the days on the calendar.

I've begun a port of this calendar component, and you can see an initial port at http://janmiksovsky.github.io/quetzal/ in the quetzal-calendar-month element. (Use Canary for now.) However, because of the present bug/limitation discussed here, it's unclear to me how I can make a fully general purpose month calendar that lets the host supply an element class which should be used to render the days. The problem is that the month calendar would appear to know the inheritance hierarchy of an element in order to correctly instantiate that element.

To state the general problem: can you write a function that, given a string tagName, returns an instance of the element class indicated by tagName? Significantly, the function must work for any type of element:

  1. A custom element like <my-test-element>.
  2. A standard HTML element tag like <button>.
  3. A class deriving from a standard HTML element, such as <my-button>, where my-button extends="button".

I don't see how such a function can be written with the present restriction. Case 1 can be implemented with document.createElement(tagName), and cases 2-3 can be handled with document.createElement(baseElement) and, in case 3, setting "is=tagName". But there's no obvious way to distinguish case 1 from case 3, is there? Even if this were feasible, it seems deeply odd that document.createElement() doesn't solve this need.

@sorvell
Copy link
Contributor

sorvell commented Nov 1, 2013

Here's the relevant portion of the spec:

https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/custom/index.html#extensions-to-document-interface-to-instantiate

On Fri, Nov 1, 2013 at 1:36 PM, Jan Miksovsky [email protected]:

Is that a permanent restriction, or is this still up for debate?

I ask because this point would be a significant limitation for a number of
elements I'm working on. I'm porting some elements from an earlier web
component framework to Polymer. A number of those components create
sub-components, and let the host specify the class for those sub-components.

Take the example of a month calendar element of the type seen at
http://quickui.org/catalog/CalendarMonth. (This uses an older component
framework called QuickUI.) This component attempts to deliver a very
general-purpose month calendar that can be extended in ways that go far
beyond what's possible in CSS. Towards that end, the component allows a
host to specify the element class that should be used to render the
individual days in the month calendar.

By default, the month calendar uses a simple baseline element class that
just renders a date, but the month calendar component allows this baseline
class to be swapped out for a different element class that can supply its
own subtree. For example, this same month calendar is used as the basis for
a CalendarMonthNavigatorhttp://quickui.org/catalog/CalendarMonthNavigator/component in which the day elements are rendered with an element class
whose representation includes a button, in order to make dates fully
clickable. A more elaborate calligraphy calendar demohttp://quickui.org/demos/kanjiCalendar/supplies a day element class that renders a day with both Arabic numerals
and kanji calligraphy. For that degree of customizability, CSS is
insufficient — one needs the ability to specific both DOM content and
behavior. And the best way to supply content and behavior is with a custom
element. That is, one wants to be able to set an attribute on the month
calendar that indicates which element class should be instantiated to
represent the days on the calendar.

I've begun a port of this calendar component, and you can see an initial
port at http://janmiksovsky.github.io/quetzal/ in the
quetzal-calendar-month element. (Use Canary for now.) However, because of
the present bug/limitation discussed here, it's unclear to me how I can
make a fully general purpose month calendar that lets the host supply an
element class which should be used to render the days. The problem is that
the month calendar would appear to know the inheritance hierarchy of an
element in order to correctly instantiate that element.

To state the general problem: can you write a function that, given a
string tagName, returns an instance of the element class indicated by
tagName? Significantly, the function must work for any type of element:

  1. A custom element like .
  2. A standard HTML element tag like .
  3. A class deriving from a standard HTML element, such as ,
    where my-button extends="button".

I don't see how such a function can be written with the present
restriction. Case 1 can be implemented with
document.createElement(tagName), and cases 2-3 can be handled with
document.createElement(baseElement) and, in case 3, setting "is=tagName".
But there's no obvious way to distinguish case 1 from case 3, is there?
Even if this were feasible, it seems deeply odd that
document.createElement() doesn't solve this need.


Reply to this email directly or view it on GitHubhttps://github.com//issues/334#issuecomment-27598825
.

@JanMiksovsky
Copy link
Author

It's a little hard for me to read these specs, but based on what my little brain can understand, an element like my-button that extends button needs to be instantiated with document.createElement("button", "my-button").

If that's the correct, then given just a tagName, how does one know which form to call: createElement(tagName) or document.createElement(baseTagName, tagName)? Is a function like the one described above — call it createAnyElement(tagName) — even possible?

I'm unclear on whether it's even possible to obtain the registration information for an element just given its tag name, and whether you'd get sufficient information to determine which form of createElement you'd need to call. I thought I could walk up the prototype chain, but in order to do that, I have to first be holding an instance of the desired element in my hand. And to do that, I'd need to know which form of createElement() to call — leaving me back at square one.

@sorvell
Copy link
Contributor

sorvell commented Nov 2, 2013

This is a reasonable complaint, and we've made it as well, but I don't
think there's a spec bug. I recommend filing one.

You do have to know if the element is a type extension or not before you
create it.

On Fri, Nov 1, 2013 at 3:48 PM, Jan Miksovsky [email protected]:

It's a little hard for me to read these specs, but based on what my little
brain can understand, an element like my-button that extends button needs
to be instantiated with document.createElement("button", "my-button").

If that's the correct, then given just a tagName, how does one know which
form to call: createElement(tagName) or document.createElement(baseTagName,
tagName)? Is a function like the one described above — call it
createAnyElement(tagName) — even possible?

I'm unclear on whether it's even possible to obtain the registration
information for an element just given its tag name, and whether you'd get
sufficient information to determine which form of createElement you'd need
to call. I thought I could walk up the prototype chain, but in order to do
that, I have to first be holding an instance of the desired element in my
hand. And to do that, I'd need to know which form of createElement() to
call — leaving me back at square one.


Reply to this email directly or view it on GitHubhttps://github.com//issues/334#issuecomment-27607084
.

@JanMiksovsky
Copy link
Author

Okay. I¹ve been pointed at lots of bug databases for web component-related
things ‹ which one is the database for spec bugs?

Aside: I¹m not aware of whether there¹s any means to ask the browser
questions about which elements are registered. E.g., it¹d be nice to be able
to find the constructor registered for a given tag name. In the polyfilled
world, I can look in CustomElements.registry. Is there any spec¹ed
equivalent for that in the native world?

From: Steve Orvell [email protected]
Reply-To: Polymer/polymer
<reply+i-21975115-f1c1f0aa1b6cfb13cea9c132e702d40a68ca064a-86139@reply.githu
b.com>
Date: Friday, November 1, 2013 at 5:04 PM
To: Polymer/polymer [email protected]
Cc: Jan Miksovsky [email protected]
Subject: Re: [polymer] test-button element class with extends="button"
can't be instantiated with syntax (#334)

This is a reasonable complaint, and we've made it as well, but I don't
think there's a spec bug. I recommend filing one.

You do have to know if the element is a type extension or not before you
create it.

On Fri, Nov 1, 2013 at 3:48 PM, Jan Miksovsky [email protected]:

It's a little hard for me to read these specs, but based on what my little
brain can understand, an element like my-button that extends button needs
to be instantiated with document.createElement("button", "my-button").

If that's the correct, then given just a tagName, how does one know which
form to call: createElement(tagName) or document.createElement(baseTagName,
tagName)? Is a function like the one described above ‹ call it
createAnyElement(tagName) ‹ even possible?

I'm unclear on whether it's even possible to obtain the registration
information for an element just given its tag name, and whether you'd get
sufficient information to determine which form of createElement you'd need
to call. I thought I could walk up the prototype chain, but in order to do
that, I have to first be holding an instance of the desired element in my
hand. And to do that, I'd need to know which form of createElement() to
call ‹ leaving me back at square one.


Reply to this email directly or view it on
GitHubhttps://github.com//issues/334#issuecomment-27607084
.


Reply to this email directly or view it on GitHub
#334 (comment) .

@sorvell
Copy link
Contributor

sorvell commented Nov 2, 2013

Easiest way is to use the links at the top right of this page:

https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/custom/index.html

Getting info about what elements have been registered is another reasonable
request, imo.

On Fri, Nov 1, 2013 at 5:15 PM, Jan Miksovsky [email protected]:

Okay. I¹ve been pointed at lots of bug databases for web component-related
things ‹ which one is the database for spec bugs?

Aside: I¹m not aware of whether there¹s any means to ask the browser
questions about which elements are registered. E.g., it¹d be nice to be
able
to find the constructor registered for a given tag name. In the polyfilled
world, I can look in CustomElements.registry. Is there any spec¹ed
equivalent for that in the native world?

From: Steve Orvell [email protected]
Reply-To: Polymer/polymer

<reply+i-21975115-f1c1f0aa1b6cfb13cea9c132e702d40a68ca064a-86139@reply.githu
b.com>
Date: Friday, November 1, 2013 at 5:04 PM
To: Polymer/polymer [email protected]
Cc: Jan Miksovsky [email protected]
Subject: Re: [polymer] test-button element class with extends="button"
can't be instantiated with syntax (#334)

This is a reasonable complaint, and we've made it as well, but I don't
think there's a spec bug. I recommend filing one.

You do have to know if the element is a type extension or not before you
create it.

On Fri, Nov 1, 2013 at 3:48 PM, Jan Miksovsky [email protected]:

It's a little hard for me to read these specs, but based on what my
little
brain can understand, an element like my-button that extends button
needs
to be instantiated with document.createElement("button",
"my-button").

If that's the correct, then given just a tagName, how does one know
which
form to call: createElement(tagName) or
document.createElement(baseTagName,
tagName)? Is a function like the one described above ‹ call it
createAnyElement(tagName) ‹ even possible?

I'm unclear on whether it's even possible to obtain the registration
information for an element just given its tag name, and whether you'd
get
sufficient information to determine which form of createElement you'd
need
to call. I thought I could walk up the prototype chain, but in order
to do
that, I have to first be holding an instance of the desired element
in my
hand. And to do that, I'd need to know which form of
createElement() to
call ‹ leaving me back at square one.


Reply to this email directly or view it on
GitHub<
https://github.com/Polymer/polymer/issues/334#issuecomment-27607084>
.


Reply to this email directly or view it on GitHub
#334 (comment) .


Reply to this email directly or view it on GitHubhttps://github.com//issues/334#issuecomment-27610381
.

@JanMiksovsky
Copy link
Author

Steve: thanks for the pointer. I've filed two bugs:

https://www.w3.org/Bugs/Public/show_bug.cgi?id=23808 deals with the original bug here.
https://www.w3.org/Bugs/Public/show_bug.cgi?id=23809 deals with the general request for an element registry.

Please add your own thoughts and/or forward to other interested parties.

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

No branches or pull requests

3 participants