Matt-Esch / virtual-dom

A Virtual DOM and diffing algorithm
MIT License
11.66k stars 779 forks source link

Cannot create Custom Elements via Type Extensions #324

Open craig0990 opened 8 years ago

craig0990 commented 8 years ago

I'm creating a new issue to continue on from #111, partly because that issue is closed, partly because this is a separate issue in it's own right (personal opinion), partly just to get a bit more visibility (selfish streak), and lastly because the FAQ says "If you have any questions not on this list, then please open an issue and ask".

Great work on the library, by the way, and nice coding style...

ISSUE

I'm trying to use Custom Elements with virtual-dom. I can create custom tags, but I cannot create type extensions.

This seems to be because document.createElement in create-element.js is not being called with the second parameter - e.g. document.createElement('li', 'todo-item').

ATTEMPTED SOLUTIONS

I have tried setting the is attribute, but it doesn't work, probably because the spec says:

After a custom element is instantiated, changing the value of the is attribute must not affect this element's custom element type.

I have also looked at hooks, widgets, and the FAQ, but none of them seem to solve this problem:

SUGGESTIONS

A naive change to create-element.js would be to check properties.attributes for an is key, and call document.createElement accordingly. I'm not sure what this does to cross-browser support, however.

The only other option I can think of is to amend the signature of createElement to add a type extension parameter, but that feels even more kludgy than writing props && props.attributes && props.attributes.is.

QUESTIONS

Am I missing something? I will create a pull request shortly with the naive fix suggested above, but how exactly should cross-browser compatibility be handled (particularly IE)?

I would imagine that adding calling document.createElement with an extra parameter will not cause any issues in older browsers, and it could be the implementer's responsibility to poly-fill where appropriate, but I wanted to check this assumption first.

CODE

Creating a custom tag with virtual-dom (works):

var MyItemProto = Object.create(HTMLElement.prototype);

MyItemProto.createdCallback = function() {
  console.log('my-item created');
};

document.registerElement('my-item', {
  prototype: MyItemProto
});

document.body.appendChild(createElement(h('my-item')));

Creating a type extension with virtual-dom (doesn't work):

var MyItemProto = Object.create(HTMLLIElement.prototype);

MyItemProto.createdCallback = function() {
  console.log('my-item created');
};

document.registerElement('my-item', {
  prototype: MyItemProto,
  extends: 'li'
});

document.body.appendChild(createElement(h('li', {
  attributes: {
    is: 'my-item'
  }
})));
craig0990 commented 8 years ago

As mentioned above, please refer to pull request #325.

Since the tests pass on my machine, I sincerely hope Travis CI passes ;)