Re: [w3c/webcomponents] :unresolved vs :not(:upgraded) (#418)

Timing issues are still a problem. This works well:

```html
<my-el id="el"></my-el>

<script>
 const defined = el.matches(':defined')

 // This code needs to do something once the element is defined.
 if (defined) {
  console.log('el is defined')
 } else {
  console.log('el not yet defined')
  customElements.whenDefined(el.tagName.toLowerCase()).then(() => {
   console.log('el is defined? ', el.matches(':defined')) // true (good)
  })
 }
</script>

<!-- Definition happens sometime later: -->
<script>
 customElements.define('my-el', class extends HTMLElement {
  constructor() {
   super()
   console.log('my-el constructor')
  }
  connectedCallback() {
   console.log('my-el connected')
  }
 })
</script>
```

[codepen example](https://codepen.io/trusktr/pen/de05b6bc70b2ae3352fbc398d4e3b444)

But this does not work:

```html
<script>
 const el = document.createElement('my-el')
 const defined = el.matches(':defined')

 // This code needs to do something once the element is defined (upgraded).
 if (defined) {
  console.log('el is defined')
 } else {
  console.log('el not yet defined')
  customElements.whenDefined(el.tagName.toLowerCase()).then(() => {
   console.log('el is defined? ', el.matches(':defined')) // false (bad)
  })
 }
</script>

<!-- Definition happens sometime later: -->
<script>
 customElements.define('my-el', class extends HTMLElement {
  constructor() {
   super()
   console.log('my-el constructor')
  }
  connectedCallback() {
   console.log('my-el connected')
  }
 })
</script>

<!-- The element is appended sometime later: -->
<script>
  document.body.append(el)
</script>
```

[codepen example](https://codepen.io/trusktr/pen/2fbf39c2913714546f1522cbbc5e2c06)

I think there should be a better solution to this. Some possible solutions:

1. Upgrade the element reference even if it is not in the DOM. In the second example, the `customElements.define` call would run the constructor, and `:defined` would be true before the `whenDefined.then` callback runs. This would greatly improve intuitiveness of code that wishes to rely on `whenDefined`
  The current output of the second example is
  ```
  el not yet defined
  el is defined?  false
  my-el constructor
  my-el connected
  ```
  but the new output would be
  ```
  el not yet defined
  my-el constructor
  el is defined?  true
  my-el connected
  ```
2. Provide a new builtin API to allow waiting for an element to be upgraded. f.e. `el.addEventListener('defined', () => {...})` . This does not improve the intuitiveness of `whenDefined` code, but provides a workaround in a non-breaking way as this would not change behavior of existing code in the wild. (I still prefer the first option).

(cc @justinfagnani as you've discussed these sorts of issues in other topics too)

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/w3c/webcomponents/issues/418#issuecomment-685896020

Received on Wednesday, 2 September 2020 17:48:34 UTC