Re: [Custom Elements] They are globals.

On Mon, Apr 11, 2016 at 4:44 PM, Ryosuke Niwa <rniwa@apple.com> wrote:
> You'd have to instead write it as "new SomeClass(this.shadowRoot)" and then (1) needs to be modified as: `super(..arguments)` to pass the argument along to the HTMLElement constructor.

For sure, similar to the examples in the GitHub issue. :]

React doesn't encourage the instantiation of element classes directly.
What if browsers did that too and threw errors whenever someone tried
to instantiate a class using `new` that extended from any of the
native classes:

```js
import {SomeElement} from 'some-library'

// this would cause a `TypeError: Illegal constructor` or something
let el = new SomeElement()

// does not return a constructor
shadowRoot1.registerElement('any-name', SomeElement)

// only this instantiation method is allowed
let el1 = shadowRoot1.createElement('any-name')

// we can use the same class in a different component where
// <any-name> is already defined but isn't backed by SomeElement
shadowRoot2.registerElement('other-name', SomeElement)
let el2 = shadowRoot2.createElement('other-name')

// maybe this should throw an error instead of returning
// HTMLUnknownElement, otherwise it might hide the obvious
// human error instead teaching the developer
shadowRoot1.registerElement('a-name', SomeElement)
let el3 = shadowRoot2.createElement('a-name')

// this would cause an error because el1 was created from
// shadowRoot1 so el1 doesn't work in shadowRoot2
shadowRoot2.appendChild(el1)
```

ShadowDOM is still evolving and the Web Component spec hasn't
officially settled, so I think there's a good opportunity here for the
web to be more helpful by throwing errors and not being ambiguous as
for example in `document.createElement('ths-has-a-typo')`.

TLDR - ShadowDOM could be the encapsulation of HTML to Custom Elements
as JSX is the encapsulation of HTML to React Components (in a morphed
way, as obviously the mechanics are different).

Here's what a small component might look like:

```js
//  --------------- HandyForm.js
import AwesomeButton from './AwesomeButton'
import { FancyForm, FancyInput } from './FancyForm'

export default
class HandyForm extends HTMLElement {
    constructor() {
        this.root = this.createShadowRoot()
        this.root.registerElement('<cool-button>', AwesomeButton)
        this.root.registerElement('<fancy-form>', FancyForm)
        this.root.registerElement('<fancy-input>', FancyInput)

        const frag = document.createDocumentFragment()
        frag.innerHTML = `
            <div>
                <fancy-form>
                    <fancy-input type="text" /> <!-- allow
self-closing tags, pleeeease -->
                    <cool-button type="submit"></cool-button>
                </fancy-form>
            </div>
        `
        this.root.appendChild(frag)
    }

    static get observedAttributes() { return [ ... ] }

    connectedCallback() { ... }
    disconnectedCallback() { ... }
    attributeChangedCallback() { ... }
}

//  --------------- app.js
import HandyForm from './HandyForm'

// elements registered on the document won't cross into shadow roots
document.registerElement('handy-form', HandyForm)
document.body.appendChild(document.createElement('handy-form'))
```

- Joe

/#!/JoePea

Received on Tuesday, 12 April 2016 08:02:44 UTC